home *** CD-ROM | disk | FTP | other *** search
/ PC World 2008 February (DVD) / PCWorld_2008-02_DVD.iso / v cisle / PHP / PHP.exe / xampp-win32-1.6.5-installer.exe / php / PEAR / HTML / Progress2.php < prev    next >
Encoding:
PHP Script  |  2007-12-20  |  134.0 KB  |  3,854 lines

  1. <?php
  2. /**
  3.  * HTML loading bar with only PHP and JS interface.
  4.  *
  5.  * PHP versions 4 and 5
  6.  *
  7.  * LICENSE: This source file is subject to version 3.01 of the PHP license
  8.  * that is available through the world-wide-web at the following URI:
  9.  * http://www.php.net/license/3_01.txt.  If you did not receive a copy of
  10.  * the PHP License and are unable to obtain it through the web, please
  11.  * send a note to license@php.net so we can mail you a copy immediately.
  12.  *
  13.  * @category   HTML
  14.  * @package    HTML_Progress2
  15.  * @author     Laurent Laville <pear@laurent-laville.org>
  16.  * @copyright  2005-2007 The PHP Group
  17.  * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
  18.  * @version    CVS: $Id: Progress2.php,v 1.33 2007/01/03 16:44:05 farell Exp $
  19.  * @link       http://pear.php.net/package/HTML_Progress2
  20.  * @since      File available since Release 2.0.0RC1
  21.  */
  22.  
  23. require_once 'HTML/Common.php';
  24. require_once 'HTML/CSS.php';
  25. require_once 'Event/Dispatcher.php';
  26.  
  27. if (version_compare(phpversion(), '5.0.0', '<')) {
  28.     include_once 'PHP/Compat.php';
  29.     PHP_Compat::loadFunction('ob_get_clean');
  30.     PHP_Compat::loadConstant('PHP_EOL');
  31. }
  32.  
  33. /**#@+
  34.  * Progress Bar shape types
  35.  *
  36.  * @var        integer
  37.  * @since      2.0.0
  38.  */
  39. define ('HTML_PROGRESS2_BAR_HORIZONTAL', 1);
  40. define ('HTML_PROGRESS2_BAR_VERTICAL',   2);
  41. define ('HTML_PROGRESS2_POLYGONAL',      3);
  42. define ('HTML_PROGRESS2_CIRCLE',         4);
  43. /**#@-*/
  44.  
  45. /**#@+
  46.  * Progress Bar label types
  47.  *
  48.  * @var        string
  49.  * @since      2.0.0
  50.  */
  51. define ('HTML_PROGRESS2_LABEL_TEXT',     'text');
  52. define ('HTML_PROGRESS2_LABEL_BUTTON',   'button');
  53. define ('HTML_PROGRESS2_LABEL_STEP',     'step');
  54. define ('HTML_PROGRESS2_LABEL_PERCENT',  'percent');
  55. define ('HTML_PROGRESS2_LABEL_CROSSBAR', 'crossbar');
  56. /**#@-*/
  57.  
  58. /**
  59.  * Basic error code that indicate an unknown message
  60.  *
  61.  * @var        integer
  62.  * @since      2.0.0
  63.  */
  64. define ('HTML_PROGRESS2_ERROR_UNKNOWN',            -1);
  65.  
  66. /**
  67.  * Basic error code that indicate a wrong input
  68.  *
  69.  * @var        integer
  70.  * @since      2.0.0
  71.  */
  72. define ('HTML_PROGRESS2_ERROR_INVALID_INPUT',    -100);
  73.  
  74. /**
  75.  * Basic error code that indicate a wrong callback definition.
  76.  * Allows only function or class-method structure.
  77.  *
  78.  * @var        integer
  79.  * @since      2.0.0
  80.  */
  81. define ('HTML_PROGRESS2_ERROR_INVALID_CALLBACK', -101);
  82.  
  83. /**
  84.  * Basic error code that indicate a deprecated method
  85.  * that may be removed at any time from a future version
  86.  *
  87.  * @var        integer
  88.  * @since      2.0.0
  89.  */
  90. define ('HTML_PROGRESS2_ERROR_DEPRECATED',       -102);
  91.  
  92. /**
  93.  * Basic error code that indicate an invalid option.
  94.  *
  95.  * @var        integer
  96.  * @since      2.0.0
  97.  */
  98. define ('HTML_PROGRESS2_ERROR_INVALID_OPTION',   -103);
  99.  
  100.  
  101. /**
  102.  * HTML loading bar with only PHP and JS interface.
  103.  *
  104.  * The HTML_Progress2 class allow you to add a loading bar
  105.  * to any of your xhtml document.
  106.  * You should have a browser that accept DHTML feature.
  107.  *
  108.  * Here is a basic example:
  109.  * <code>
  110.  * <?php
  111.  * require_once 'HTML/Progress2.php';
  112.  *
  113.  * $pb = new HTML_Progress2();
  114.  * $pb->setAnimSpeed(50);
  115.  * ?>
  116.  * <html>
  117.  * <head>
  118.  * <?php
  119.  * echo $pb->getStyle(false);
  120.  * echo $pb->getScript(false);
  121.  * ?>
  122.  * </head>
  123.  * <body>
  124.  * <?php
  125.  * $pb->display();
  126.  * $pb->run();
  127.  * ?>
  128.  * </body>
  129.  * </html>
  130.  * </code>
  131.  *
  132.  * @category   HTML
  133.  * @package    HTML_Progress2
  134.  * @author     Laurent Laville <pear@laurent-laville.org>
  135.  * @copyright  2005-2007 The PHP Group
  136.  * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
  137.  * @version    Release: 2.2.0
  138.  * @link       http://pear.php.net/package/HTML_Progress2
  139.  * @since      Class available since Release 2.0.0RC1
  140.  */
  141.  
  142. class HTML_Progress2 extends HTML_Common
  143. {
  144.     /**
  145.      * Status of the progress bar (new, show, hide).
  146.      *
  147.      * @var        string
  148.      * @since      2.0.0
  149.      * @access     private
  150.      */
  151.     var $_status = 'new';
  152.  
  153.     /**
  154.      * Whether the progress bar is in determinate or indeterminate mode.
  155.      * The default is false.
  156.      * An indeterminate progress bar continuously displays animation indicating
  157.      * that an operation of unknown length is occuring.
  158.      *
  159.      * @var        boolean
  160.      * @since      2.0.0
  161.      * @access     public
  162.      * @see        setIndeterminate(), isIndeterminate()
  163.      */
  164.     var $indeterminate;
  165.  
  166.     /**
  167.      * Whether to display a border around the progress bar.
  168.      * The default is false.
  169.      *
  170.      * @var        boolean
  171.      * @since      2.0.0
  172.      * @access     private
  173.      * @see        setBorderPainted(), isBorderPainted()
  174.      */
  175.     var $_paintBorder;
  176.  
  177.     /**
  178.      * The label that uniquely identifies this progress object.
  179.      *
  180.      * @var        string
  181.      * @since      2.0.0
  182.      * @access     public
  183.      * @see        getIdent(), setIdent()
  184.      */
  185.     var $ident;
  186.  
  187.     /**
  188.      * Stores the event dispatcher which handles notifications
  189.      *
  190.      * @var        array
  191.      * @since      2.0.0RC2
  192.      * @access     protected
  193.      */
  194.     var $dispatcher;
  195.  
  196.     /**
  197.      * Count the number of observer registered.
  198.      * The Event_Dispatcher will be add on first observer registration, and
  199.      * will be removed with the last observer.
  200.      *
  201.      * @var        integer
  202.      * @since      2.0.0RC2
  203.      * @access     private
  204.      */
  205.     var $_observerCount;
  206.  
  207.     /**
  208.      * Delay in milisecond before each progress cells display.
  209.      * 1000 ms === sleep(1)
  210.      * <strong>usleep()</strong> function does not run on Windows platform.
  211.      *
  212.      * @var        integer
  213.      * @since      2.0.0
  214.      * @access     public
  215.      * @see        setAnimSpeed()
  216.      */
  217.     var $animSpeed;
  218.  
  219.     /**
  220.      * Callback, either function name or array(&$object, 'method')
  221.      *
  222.      * @var        mixed
  223.      * @since      2.0.0
  224.      * @access     private
  225.      * @see        setProgressHandler()
  226.      */
  227.     var $_callback = false;
  228.  
  229.     /**
  230.      * The progress bar's minimum value.
  231.      * The default is 0.
  232.      *
  233.      * @var        integer
  234.      * @since      2.0.0
  235.      * @access     public
  236.      * @see        getMinimum(), setMinimum()
  237.      */
  238.     var $minimum;
  239.  
  240.     /**
  241.      * The progress bar's maximum value.
  242.      * The default is 100.
  243.      *
  244.      * @var        integer
  245.      * @since      2.0.0
  246.      * @access     public
  247.      * @see        getMaximum(), setMaximum()
  248.      */
  249.     var $maximum;
  250.  
  251.     /**
  252.      * The progress bar's increment value.
  253.      * The default is +1.
  254.      *
  255.      * @var        integer
  256.      * @since      2.0.0
  257.      * @access     public
  258.      * @see        getIncrement(), setIncrement()
  259.      */
  260.     var $increment;
  261.  
  262.     /**
  263.      * The progress bar's current value.
  264.      *
  265.      * @var        integer
  266.      * @since      2.0.0
  267.      * @access     public
  268.      * @see        getValue(), setvalue(), incValue()
  269.      */
  270.     var $value;
  271.  
  272.     /**
  273.      * Whether the progress bar is horizontal, vertical, polygonal or circle.
  274.      * The default is horizontal.
  275.      *
  276.      * @var        integer
  277.      * @since      2.0.0
  278.      * @access     public
  279.      * @see        getOrientation(), setOrientation()
  280.      */
  281.     var $orientation;
  282.  
  283.     /**
  284.      * Whether the progress bar is filled in 'natural' or 'reverse' way.
  285.      * The default fill way is 'natural'.
  286.      *
  287.      * <ul>
  288.      * <li>'way'  =  bar fill way
  289.      *   <ul>
  290.      *     <li>with Progress Bar Horizontal,
  291.      *              natural way is : left to right
  292.      *        <br />reverse way is : right to left
  293.      *     <li>with Progress Bar Vertical,
  294.      *              natural way is : down to up
  295.      *        <br />reverse way is : up to down
  296.      *     <li>with Progress Circle or Polygonal,
  297.      *              natural way is : clockwise
  298.      *        <br />reverse way is : anticlockwise
  299.      *   </ul>
  300.      * </ul>
  301.      *
  302.      * @var        string
  303.      * @since      2.0.0
  304.      * @access     public
  305.      * @see        getFillWay(), setFillWay()
  306.      */
  307.     var $fillWay;
  308.  
  309.     /**
  310.      * The cell count of the progress bar. The default is 10.
  311.      *
  312.      * @var        integer
  313.      * @since      2.0.0
  314.      * @access     public
  315.      * @see        getCellCount(), setCellCount()
  316.      */
  317.     var $cellCount;
  318.  
  319.     /**
  320.      * The cell coordinates for a progress polygonal shape.
  321.      *
  322.      * @var        array
  323.      * @since      2.0.0
  324.      * @access     private
  325.      * @see        getCellCoordinates(), setCellCoordinates()
  326.      */
  327.     var $_coordinates;
  328.  
  329.     /**
  330.      * The width of grid in cell-size of the polygonal shape.
  331.      *
  332.      * @var        integer
  333.      * @since      2.0.0
  334.      * @access     private
  335.      * @see        getCellCoordinates(), setCellCoordinates()
  336.      */
  337.     var $_xgrid;
  338.  
  339.     /**
  340.      * The height of grid in cell-size of the polygonal shape.
  341.      *
  342.      * @var        integer
  343.      * @since      2.0.0
  344.      * @access     private
  345.      * @see        getCellCoordinates(), setCellCoordinates()
  346.      */
  347.     var $_ygrid;
  348.  
  349.     /**
  350.      * Progress bar core properties
  351.      *
  352.      * <code>
  353.      * $progress = array(
  354.      *    'background-color' => '#FFFFFF',      # bar background color
  355.      *    'background-image' => 'none',         # bar background image
  356.      *    'background-repeat' => 'no-repeat',   # bar background image repeat option
  357.      *    'background-position' => 'top left',  # bar background image start position
  358.      *    'width' => 0,                     # bar width
  359.      *    'height' => 0,                    # bar height
  360.      *    'left' => 10,                     # position from left
  361.      *    'top' => 25,                      # position from top
  362.      *    'position' => 'relative'          # position absolute or relative
  363.      * );
  364.      * </code>
  365.      *
  366.      * @var        array
  367.      * @since      2.0.0
  368.      * @access     private
  369.      * @see        getProgressAttributes(), setProgressAttributes()
  370.      */
  371.     var $_progress = array();
  372.  
  373.     /**
  374.      * Progress bar frame properties
  375.      *
  376.      * <code>
  377.      * $frame = array(
  378.      *    'show' => false,      # frame show (true/false)
  379.      *    'left' => 200,        # position from left
  380.      *    'top' => 100,         # position from top
  381.      *    'width' => 320,       # width
  382.      *    'height' => 90,       # height
  383.      *    'color' => '#C0C0C0', # color
  384.      *    'border-width' => 2,                                   # border width
  385.      *    'border-style' => 'solid',                             # border style
  386.      *                                                           # (solid, dashed, dotted ...)
  387.      *    'border-color' => '#DFDFDF #404040 #404040 #DFDFDF'    # border color (3dfx)
  388.      * );
  389.      * </code>
  390.      *
  391.      * @var        array
  392.      * @since      2.0.0
  393.      * @access     public
  394.      * @see        getFrameAttributes(), setFrameAttributes()
  395.      */
  396.     var $frame = array();
  397.  
  398.     /**
  399.      * Progress bar border properties
  400.      *
  401.      * <code>
  402.      * $border = array(
  403.      *    'class' => 'progressBorder%s',    # css class selector
  404.      *    'width' => 0,                     # width size in pixel
  405.      *    'style' => 'solid',               # style (solid, dashed, dotted ...)
  406.      *    'color' => '#000000'              # color
  407.      * );
  408.      * </code>
  409.      *
  410.      * @var        array
  411.      * @since      2.0.0
  412.      * @access     public
  413.      * @see        getBorderAttributes(), setBorderAttributes()
  414.      */
  415.     var $border = array();
  416.  
  417.     /**
  418.      * Progress bar cells properties
  419.      *
  420.      * <code>
  421.      * $cell = array(
  422.      *    'id' => 'pcel%01s',                    # cell identifier mask
  423.      *    'class' => 'cell%s',                   # css class selector
  424.      *    'active-color' => '#006600',           # active color
  425.      *    'inactive-color' => '#CCCCCC',         # inactive color
  426.      *    'font-family' => 'Courier, Verdana',   # font family
  427.      *    'font-size' => 8,                      # font size
  428.      *    'color' => '#000000',                  # foreground color
  429.      *    'background-color' => '#FFFFFF',       # background color
  430.      *    'background-image' => 'none',          # cell background image
  431.      *    'background-repeat' => 'no-repeat',    # cell background image repeat option
  432.      *    'background-position' => 'top left',   # cell background image start position
  433.      *    'width' => 15,                         # cell width
  434.      *    'height' => 20,                        # cell height
  435.      *    'spacing' => 2                         # cell spacing
  436.      * );
  437.      * </code>
  438.      *
  439.      * @var        array
  440.      * @since      2.0.0
  441.      * @access     public
  442.      * @see        getCellAttributes(), setCellAttributes()
  443.      */
  444.     var $cell = array();
  445.  
  446.     /**
  447.      * Progress bar labels properties
  448.      *
  449.      * <code>
  450.      * $label = array(
  451.      *    'name' => array(                  # label name
  452.      *      'type' => 'text',               # label type
  453.      *                                      # (text,button,step,percent,crossbar)
  454.      *      'value' => ' ',            # label value
  455.      *      'left' => ($left),              # label position from left
  456.      *      'top' => ($top - 16),           # label position from top
  457.      *      'width' => 0,                   # label width
  458.      *      'height' => 0,                  # label height
  459.      *      'align' => 'left',              # label align
  460.      *      'background-color' => 'transparent',          # label background color
  461.      *      'font-family' => 'Verdana, Tahoma, Arial',    # label font family
  462.      *      'font-size' => 11,                            # label font size
  463.      *      'font-weight' => 'normal',                    # label font weight
  464.      *      'color' => '#000000',                         # label font color
  465.      *      'class' => 'progressPercentLabel%s'           # css class selector
  466.      * );
  467.      * </code>
  468.      *
  469.      * @var        array
  470.      * @since      2.0.0
  471.      * @access     public
  472.      * @see        getLabelAttributes(), setLabelAttributes()
  473.      */
  474.     var $label = array();
  475.  
  476.     /**
  477.      * External Javascript file to override internal default code
  478.      *
  479.      * @var        string
  480.      * @since      2.0.0
  481.      * @access     public
  482.      * @see        getScript(), setScript()
  483.      */
  484.     var $script;
  485.  
  486.     /**
  487.      * Error message callback.
  488.      * This will be used to generate the error message
  489.      * from the error code.
  490.      *
  491.      * @var        false|string|array
  492.      * @since      2.0.0
  493.      * @access     private
  494.      * @see        _initErrorHandler()
  495.      */
  496.     var $_callback_message = false;
  497.  
  498.     /**
  499.      * Error context callback.
  500.      * This will be used to generate the error context for an error.
  501.      *
  502.      * @var        false|string|array
  503.      * @since      2.0.0
  504.      * @access     private
  505.      * @see        _initErrorHandler()
  506.      */
  507.     var $_callback_context = false;
  508.  
  509.     /**
  510.      * Error push callback.
  511.      * The return value will be used to determine whether to allow
  512.      * an error to be pushed or logged.
  513.      *
  514.      * @var        false|string|array
  515.      * @since      2.0.0
  516.      * @access     private
  517.      * @see        _initErrorHandler()
  518.      */
  519.     var $_callback_push = false;
  520.  
  521.     /**
  522.      * Error handler callback.
  523.      * This will handle any errors raised by this package.
  524.      *
  525.      * @var        false|string|array
  526.      * @since      2.0.0
  527.      * @access     private
  528.      * @see        _initErrorHandler()
  529.      */
  530.     var $_callback_errorhandler = false;
  531.  
  532.     /**
  533.      * Associative array of key-value pairs
  534.      * that are used to specify any handler-specific settings.
  535.      *
  536.      * @var        array
  537.      * @since      2.0.0
  538.      * @access     private
  539.      * @see        _initErrorHandler()
  540.      */
  541.     var $_errorhandler_options = array();
  542.  
  543.     /**
  544.      * Error stack for this package.
  545.      *
  546.      * @var        array
  547.      * @since      2.0.0
  548.      * @access     private
  549.      * @see        raiseError()
  550.      */
  551.     var $_errorstack = array();
  552.  
  553.  
  554.     /**
  555.      * Constructor (ZE1)
  556.      *
  557.      * @since      2.0.0
  558.      * @access     public
  559.      */
  560.     function HTML_Progress2($errorPrefs = array(),
  561.                             $orient = HTML_PROGRESS2_BAR_HORIZONTAL, $min = 0, $max = 100,
  562.                             $percentLabel = 'pct1')
  563.     {
  564.         $this->__construct($errorPrefs, $orient, $min, $max, $percentLabel);
  565.     }
  566.  
  567.     /**
  568.      * Constructor (ZE2) Summary
  569.      *
  570.      *   Creates a natural horizontal progress bar that displays ten separated cells
  571.      *   with no border and only percent label.
  572.      *   The initial and minimum values are 0, and the maximum is 100.
  573.      *
  574.      * @param      array     $errorPrefs    (optional) Hash of params to configure error handler
  575.      * @param      int       $orient        (optional) Orientation of progress bar
  576.      * @param      int       $min           (optional) Minimum value of progress bar
  577.      * @param      int       $max           (optional) Maximum value of progress bar
  578.      * @param      mixed     $percentLabel  (optional) Progress bar percent label id.
  579.      *
  580.      * @since      2.0.0
  581.      * @access     protected
  582.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  583.      * @see        setIndeterminate(), setIdent(), setAnimSpeed(),
  584.      *             setOrientation(), setMinimum(), setMaximum(), addLabel()
  585.      */
  586.     function __construct($errorPrefs = array(),
  587.                          $orient = HTML_PROGRESS2_BAR_HORIZONTAL, $min = 0, $max = 100,
  588.                          $percentLabel = 'pct1')
  589.     {
  590.         $this->_initErrorHandler($errorPrefs);
  591.  
  592.         $this->_observerCount = 0;
  593.  
  594.         $this->value = 0;
  595.         $this->minimum = 0;
  596.         $this->maximum = 100;
  597.         $this->increment = +1;
  598.  
  599.         $this->cellCount = 10;
  600.         $this->orientation = HTML_PROGRESS2_BAR_HORIZONTAL;
  601.         $this->fillWay = 'natural';         // fill bar from left to right
  602.         $this->script = null;               // uses internal javascript code
  603.  
  604.         $this->frame  = array('show' => false);
  605.         $this->_progress = array(
  606.             'background-color' => '#FFFFFF',
  607.             'background-image' => 'none',
  608.             'background-repeat' => 'no-repeat',
  609.             'background-position' => 'top left',
  610.             'width' => 0,
  611.             'height' => 0,
  612.             'left' => 10,
  613.             'top' => 25,
  614.             'position' => 'relative'
  615.         );
  616.         $this->border = array(
  617.             'class' => 'progressBorder%s',
  618.             'width' => 0,
  619.             'style' => 'solid',
  620.             'color' => '#000000'
  621.         );
  622.         $this->cell = array(
  623.             'id' => 'pcel%01s',
  624.             'class' => 'cell%s',
  625.             'active-color' => '#006600',
  626.             'inactive-color' => '#CCCCCC',
  627.             'font-family' => 'Courier, Verdana',
  628.             'font-size' => 8,
  629.             'color' => '#000000',
  630.             'background-color' => '#FFFFFF',
  631.             'background-image' => 'none',
  632.             'background-repeat' => 'no-repeat',
  633.             'background-position' => 'top left',
  634.             'width' => 15,
  635.             'height' => 20,
  636.             'spacing' => 2
  637.         );
  638.  
  639.         $this->_updateProgressSize();   // updates the new size of progress bar
  640.  
  641.         if (!is_int($orient)) {
  642.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  643.                 array('var' => '$orient',
  644.                       'was' => gettype($orient),
  645.                       'expected' => 'integer',
  646.                       'paramnum' => 2));
  647.  
  648.         } elseif (!is_int($min)) {
  649.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  650.                 array('var' => '$min',
  651.                       'was' => gettype($min),
  652.                       'expected' => 'integer',
  653.                       'paramnum' => 3));
  654.  
  655.         } elseif (!is_int($max)) {
  656.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  657.                 array('var' => '$max',
  658.                       'was' => gettype($max),
  659.                       'expected' => 'integer',
  660.                       'paramnum' => 4));
  661.  
  662.         } elseif (!is_string($percentLabel) && !is_bool($percentLabel)) {
  663.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  664.                 array('var' => '$percentLabel',
  665.                       'was' => gettype($percentLabel),
  666.                       'expected' => 'string | boolean',
  667.                       'paramnum' => 5));
  668.         }
  669.  
  670.         $this->setOrientation($orient);
  671.         $this->setMinimum($min);
  672.         $this->setMaximum($max);
  673.  
  674.         if ($percentLabel) {
  675.             $this->addLabel(HTML_PROGRESS2_LABEL_PERCENT, $percentLabel);
  676.         }
  677.         $this->setBorderPainted(false);
  678.         $this->setIndeterminate(false);
  679.         $this->setIdent();
  680.         $this->setAnimSpeed(0);
  681.  
  682.         // to fix a potential php config problem with PHP 4.2.0 : turn 'implicit_flush' ON
  683.         ob_implicit_flush(1);
  684.     }
  685.  
  686.     /**
  687.      * Returns the current API version.
  688.      *
  689.      * This function return a "PHP-standardized" version number string.
  690.      * This is useful if you would like to write programs working only on some
  691.      * versions of HTML_Progress2. See also php version_compare() function.
  692.      *
  693.      * @link       http://www.php.net/manual/en/function.version-compare.php
  694.      * @return     string
  695.      * @since      2.0.0
  696.      * @access     public
  697.      */
  698.     function apiVersion()
  699.     {
  700.         return '2.2.0';
  701.     }
  702.  
  703.     /**
  704.      * Returns mode of the progress meter.
  705.      *
  706.      * There are two types of progress meters: determinate and undeterminate.
  707.      *
  708.      * Determinate progress meters are used when you know the length of time
  709.      * that an operation will take. The progress meter will fill up and,
  710.      * once full, the operation should be finished.
  711.      *
  712.      * Undeterminate progress meters are used when you do not know the length
  713.      * of time of an operation. The progress meter will have an animation
  714.      * such a sliding box.
  715.      *
  716.      * @return     boolean
  717.      * @since      2.0.0
  718.      * @access     public
  719.      * @see        setIndeterminate()
  720.      */
  721.     function isIndeterminate()
  722.     {
  723.         return $this->indeterminate;
  724.     }
  725.  
  726.     /**
  727.      * Sets the mode of progress meter.
  728.      *
  729.      * Default progress meters are in determinate mode ($continuous = TRUE), but
  730.      * can be switched anytime in indeterminate mode ($continuous = FALSE).
  731.      *
  732.      * @param      boolean   $continuous    whether countinuously displays animation
  733.      *
  734.      * @return     void
  735.      * @since      2.0.0
  736.      * @access     public
  737.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  738.      * @see        isIndeterminate()
  739.      */
  740.     function setIndeterminate($continuous)
  741.     {
  742.         if (!is_bool($continuous)) {
  743.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  744.                 array('var' => '$continuous',
  745.                       'was' => gettype($continuous),
  746.                       'expected' => 'boolean',
  747.                       'paramnum' => 1));
  748.         }
  749.         $this->indeterminate = $continuous;
  750.     }
  751.  
  752.     /**
  753.      * Determines whether the progress bar border is painted or not.
  754.      *
  755.      * By default, each progress bar (horizontal, vertical) has no border.
  756.      * This function gave ability to know if you've already set a border
  757.      * (return TRUE), or not (return FALSE).
  758.      *
  759.      * @return     boolean
  760.      * @since      2.0.0
  761.      * @access     public
  762.      * @see        setBorderPainted()
  763.      */
  764.     function isBorderPainted()
  765.     {
  766.         return $this->_paintBorder;
  767.     }
  768.  
  769.     /**
  770.      * Decides to paint or not a border to the progress bar.
  771.      *
  772.      * This function gave ability to set ($paint = TRUE) or remove ($paint = FALSE)
  773.      * a border to the current progress bar.
  774.      *
  775.      * @param      boolean   $paint         whether the progress bar should paint its border
  776.      *
  777.      * @return     void
  778.      * @since      2.0.0
  779.      * @access     public
  780.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  781.      * @see        isBorderPainted()
  782.      */
  783.     function setBorderPainted($paint)
  784.     {
  785.         if (!is_bool($paint)) {
  786.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  787.                 array('var' => '$paint',
  788.                       'was' => gettype($paint),
  789.                       'expected' => 'boolean',
  790.                       'paramnum' => 1));
  791.         }
  792.  
  793.         $this->_paintBorder = $paint;
  794.     }
  795.  
  796.     /**
  797.      * Returns the progress meter minimum value.
  798.      *
  799.      * Get the minimum value at which the progress meter will start.
  800.      * The default value is zero and can't be negative.
  801.      *
  802.      * @return     integer
  803.      * @since      2.0.0
  804.      * @access     public
  805.      * @see        setMinimum()
  806.      */
  807.     function getMinimum()
  808.     {
  809.         return $this->minimum;
  810.     }
  811.  
  812.     /**
  813.      * Sets the progress meter minimum value.
  814.      *
  815.      * Set the minimum value at which the progress meter will start.
  816.      * The default value is zero and can't be negative.
  817.      * If the new minimum is different than previous value, all listeners
  818.      * are notified.
  819.      *
  820.      * @param      integer   $min           progress meter's minimal value
  821.      *
  822.      * @return     void
  823.      * @since      2.0.0
  824.      * @access     public
  825.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  826.      * @see        getMinimum()
  827.      */
  828.     function setMinimum($min)
  829.     {
  830.         if (!is_int($min)) {
  831.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  832.                 array('var' => '$min',
  833.                       'was' => gettype($min),
  834.                       'expected' => 'integer',
  835.                       'paramnum' => 1));
  836.  
  837.         } elseif ($min < 0) {
  838.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  839.                 array('var' => '$min',
  840.                       'was' => $min,
  841.                       'expected' => 'positive',
  842.                       'paramnum' => 1));
  843.  
  844.         } elseif ($min > $this->maximum) {
  845.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  846.                 array('var' => '$min',
  847.                       'was' => $min,
  848.                       'expected' => 'less than $max = '.$this->maximum,
  849.                       'paramnum' => 1));
  850.         }
  851.         $oldVal = $this->minimum;
  852.         $this->minimum = $min;
  853.  
  854.         /* set current value to minimum if less than minimum */
  855.         if ($this->value < $min) {
  856.             $this->setValue($min);
  857.         }
  858.  
  859.         if ($oldVal != $min) {
  860.             $this->_postNotification('onChange', array('handler' => __FUNCTION__, 'value' => $min));
  861.         }
  862.     }
  863.  
  864.     /**
  865.      * Returns the progress meter maximum value.
  866.      *
  867.      * Get the maximum value at which the progress meter will stop.
  868.      * The default value is 100 and can't be less than minimum.
  869.      *
  870.      * @return     integer
  871.      * @since      2.0.0
  872.      * @access     public
  873.      * @see        setMaximum()
  874.      */
  875.     function getMaximum()
  876.     {
  877.         return $this->maximum;
  878.     }
  879.  
  880.     /**
  881.      * Sets the progress meter maximum value.
  882.      *
  883.      * Set the maximum value at which the progress meter will stop.
  884.      * The default value is 100 and can't be less than minimum.
  885.      * If the new maximum is different than previous value, all listeners
  886.      * are notified.
  887.      *
  888.      * @param      integer   $max           progress meter's maximal value
  889.      *
  890.      * @return     void
  891.      * @since      2.0.0
  892.      * @access     public
  893.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  894.      * @see        getMaximum()
  895.      */
  896.     function setMaximum($max)
  897.     {
  898.         if (!is_int($max)) {
  899.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  900.                 array('var' => '$max',
  901.                       'was' => gettype($max),
  902.                       'expected' => 'integer',
  903.                       'paramnum' => 1));
  904.  
  905.         } elseif ($max < 0) {
  906.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  907.                 array('var' => '$max',
  908.                       'was' => $max,
  909.                       'expected' => 'positive',
  910.                       'paramnum' => 1));
  911.  
  912.         } elseif ($max < $this->minimum) {
  913.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  914.                 array('var' => '$max',
  915.                       'was' => $max,
  916.                       'expected' => 'greater than $min = '.$this->minimum,
  917.                       'paramnum' => 1));
  918.         }
  919.         $oldVal = $this->maximum;
  920.         $this->maximum = $max;
  921.  
  922.         /* set current value to maximum if greater to maximum */
  923.         if ($this->value > $max) {
  924.             $this->setValue($max);
  925.         }
  926.  
  927.         if ($oldVal != $max) {
  928.             $this->_postNotification('onChange', array('handler' => __FUNCTION__, 'value' => $max));
  929.         }
  930.     }
  931.  
  932.     /**
  933.      * Returns the progress meter increment value.
  934.      *
  935.      * Get step of progress property of a progress meter.
  936.      * The default value is +1.
  937.      *
  938.      * @return     integer
  939.      * @since      2.0.0
  940.      * @access     public
  941.      * @see        setIncrement()
  942.      */
  943.     function getIncrement()
  944.     {
  945.         return $this->increment;
  946.     }
  947.  
  948.     /**
  949.      * Sets the progress meter increment value.
  950.      *
  951.      * Defines step of progress property of a progress meter.
  952.      * Allows to ajust default value (+1).
  953.      *
  954.      * @param      integer   $inc           progress meter's increment value
  955.      *
  956.      * @return     void
  957.      * @since      2.0.0
  958.      * @access     public
  959.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  960.      * @see        getIncrement()
  961.      */
  962.     function setIncrement($inc)
  963.     {
  964.         if (!is_int($inc)) {
  965.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  966.                 array('var' => '$inc',
  967.                       'was' => gettype($inc),
  968.                       'expected' => 'integer',
  969.                       'paramnum' => 1));
  970.  
  971.         } elseif ($inc == 0) {
  972.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  973.                 array('var' => '$inc',
  974.                       'was' => $inc,
  975.                       'expected' => 'not equal zero',
  976.                       'paramnum' => 1));
  977.         }
  978.         $this->increment = $inc;
  979.     }
  980.  
  981.     /**
  982.      * Returns the progress meter current value.
  983.      *
  984.      * Get the current value of the progress meter that is always between
  985.      * the minimum and maximum values, inclusive.
  986.      * The default value is equal to minimum.
  987.      *
  988.      * @return     integer
  989.      * @since      2.0.0
  990.      * @access     public
  991.      * @see        setValue(), incValue()
  992.      */
  993.     function getValue()
  994.     {
  995.         return $this->value;
  996.     }
  997.  
  998.     /**
  999.      * Sets the progress meter current value.
  1000.      *
  1001.      * Set the current value of the progress meter that is always between
  1002.      * the minimum and maximum values, inclusive. If the new value is different
  1003.      * from previous, then all listeners are notified.
  1004.      *
  1005.      * @param      integer   $val           progress meter's current value
  1006.      *
  1007.      * @return     void
  1008.      * @since      2.0.0
  1009.      * @access     public
  1010.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  1011.      * @see        getValue(), incValue()
  1012.      */
  1013.     function setValue($val)
  1014.     {
  1015.         if (!is_int($val)) {
  1016.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  1017.                 array('var' => '$val',
  1018.                       'was' => gettype($val),
  1019.                       'expected' => 'integer',
  1020.                       'paramnum' => 1));
  1021.  
  1022.         } elseif ($val < $this->minimum) {
  1023.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  1024.                 array('var' => '$val',
  1025.                       'was' => $val,
  1026.                       'expected' => 'greater than $min = '.$this->minimum,
  1027.                       'paramnum' => 1));
  1028.  
  1029.         } elseif ($val > $this->maximum) {
  1030.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  1031.                 array('var' => '$val',
  1032.                       'was' => $val,
  1033.                       'expected' => 'less than $max = '.$this->maximum,
  1034.                       'paramnum' => 1));
  1035.         }
  1036.         $oldVal = $this->value;
  1037.         $this->value = $val;
  1038.  
  1039.         if ($oldVal != $val) {
  1040.             $this->_postNotification('onChange', array('handler' => __FUNCTION__, 'value' => $val));
  1041.         }
  1042.     }
  1043.  
  1044.     /**
  1045.      * Updates the internal progress meter current value.
  1046.      *
  1047.      * The new current value is equal to previous value increase by
  1048.      * increment value. All listeners are notified.
  1049.      * See also moveNext() method if you want a refresh display too.
  1050.      *
  1051.      * @return     void
  1052.      * @since      2.0.0
  1053.      * @access     public
  1054.      * @see        getValue(), setValue(), moveNext()
  1055.      */
  1056.     function incValue()
  1057.     {
  1058.         $newVal = $this->value + $this->increment;
  1059.         $newVal = min($this->maximum, $newVal);
  1060.         $this->value = $newVal;
  1061.  
  1062.         $this->_postNotification('onChange', array('handler' => __FUNCTION__, 'value' => $newVal));
  1063.     }
  1064.  
  1065.     /**
  1066.      * Changes new value of the progress meter by step increase.
  1067.      *
  1068.      * Move current value to the next step of the progress meter
  1069.      * defined by its increment. If result value is different than previous,
  1070.      * then all listeners are notified.
  1071.      * Caution: a step is always between 1 and (maximum / taskcount) rounded fractions up.
  1072.      *
  1073.      * @param      integer   $step          new step value
  1074.      *
  1075.      * @return     void
  1076.      * @since      2.0.0
  1077.      * @access     public
  1078.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  1079.      * @see        moveNext()
  1080.      */
  1081.     function moveStep($step)
  1082.     {
  1083.         if (!is_int($step)) {
  1084.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  1085.                 array('var' => '$step',
  1086.                       'was' => gettype($step),
  1087.                       'expected' => 'integer',
  1088.                       'paramnum' => 1));
  1089.  
  1090.         } elseif ($step < 0) {
  1091.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  1092.                 array('var' => '$step',
  1093.                       'was' => $step,
  1094.                       'expected' => 'greater than zero',
  1095.                       'paramnum' => 1));
  1096.  
  1097.         } elseif ($step > intval(ceil($this->maximum / $this->increment))) {
  1098.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  1099.                 array('var' => '$step',
  1100.                       'was' => $step,
  1101.                       'expected' => 'less than '. intval(ceil($this->maximum / $this->increment)),
  1102.                       'paramnum' => 1));
  1103.         }
  1104.         $oldVal = $this->value;
  1105.         $this->value = $step * $this->increment;
  1106.         $this->value = min($this->maximum, $this->value);
  1107.  
  1108.         if ($oldVal != $this->value) {
  1109.             $this->_refreshDisplay($this->value);
  1110.             $this->_postNotification('onChange', array('handler' => __FUNCTION__, 'value' => $step));
  1111.         }
  1112.     }
  1113.  
  1114.     /**
  1115.      * Changes new value of the progress meter by increment increase.
  1116.      *
  1117.      * Move current value to the next value of the progress meter
  1118.      * defined by its increment. If result value is different than previous,
  1119.      * then all listeners are notified.
  1120.      *
  1121.      * @return     void
  1122.      * @since      2.0.0
  1123.      * @access     public
  1124.      * @see        moveStep()
  1125.      */
  1126.     function moveNext()
  1127.     {
  1128.         $oldVal = $this->value;
  1129.         $this->value  = $oldVal + $this->increment;
  1130.         $this->value = min($this->maximum, $this->value);
  1131.  
  1132.         if ($oldVal != $this->value) {
  1133.             $this->_refreshDisplay($this->value);
  1134.             $this->_postNotification('onChange', array('handler' => __FUNCTION__, 'value' => $this->value));
  1135.         }
  1136.     }
  1137.  
  1138.     /**
  1139.      * Returns the percent complete of the progress meter.
  1140.      *
  1141.      * Note that this number is between 0.00 and 1.00 when $float = true.
  1142.      * And this number is between 0 and 100 when $float = false.
  1143.      *
  1144.      * @param      boolean   $float         (optional) float or integer format
  1145.      *
  1146.      * @return     float
  1147.      * @since      2.0.0
  1148.      * @access     public
  1149.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  1150.      * @see        getValue(), getMaximum()
  1151.      */
  1152.     function getPercentComplete($float = true)
  1153.     {
  1154.         if (!is_bool($float)) {
  1155.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  1156.                 array('var' => '$float',
  1157.                       'was' => gettype($float),
  1158.                       'expected' => 'boolean',
  1159.                       'paramnum' => 1));
  1160.         }
  1161.  
  1162.         $min = $this->minimum;
  1163.         $max = $this->maximum;
  1164.         $val = $this->value;
  1165.  
  1166.         $percent = round((($val - $min) / ($max - $min)), 4);
  1167.  
  1168.         if ($float) {
  1169.             return $percent;
  1170.         } else {
  1171.             return intval($percent * 100);
  1172.         }
  1173.     }
  1174.  
  1175.     /**
  1176.      * Returns orientation of the progress bar.
  1177.      *
  1178.      * There are only two distinct orientations for a progress bar:
  1179.      * horizontal and vertical, identified by two constants:
  1180.      * HTML_PROGRESS2_BAR_HORIZONTAL and HTML_PROGRESS2_BAR_VERTICAL.
  1181.      * While circle and other polygonal progress meter are identified by
  1182.      * two other constants: HTML_PROGRESS2_CIRCLE and HTML_PROGRESS2_POLYGONAL.
  1183.      * The default orientation is horizontal.
  1184.      *
  1185.      * @return     integer
  1186.      * @since      2.0.0
  1187.      * @access     public
  1188.      * @see        setOrientation()
  1189.      */
  1190.     function getOrientation()
  1191.     {
  1192.         return $this->orientation;
  1193.     }
  1194.  
  1195.     /**
  1196.      * Sets orientation of the progress bar.
  1197.      *
  1198.      * There are only two distinct orientations for a progress bar:
  1199.      * horizontal and vertical, identified by two constants:
  1200.      * HTML_PROGRESS2_BAR_HORIZONTAL and HTML_PROGRESS2_BAR_VERTICAL.
  1201.      * While circle and other polygonal progress meter are identified by
  1202.      * two other constants: HTML_PROGRESS2_CIRCLE and HTML_PROGRESS2_POLYGONAL.
  1203.      * The default orientation is horizontal.
  1204.      *
  1205.      * @param      integer   $orient        Orientation (horizontal or vertical)
  1206.      *
  1207.      * @return     void
  1208.      * @since      2.0.0
  1209.      * @access     public
  1210.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  1211.      * @see        getOrientation()
  1212.      */
  1213.     function setOrientation($orient)
  1214.     {
  1215.         if (!is_int($orient)) {
  1216.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  1217.                 array('var' => '$orient',
  1218.                       'was' => gettype($orient),
  1219.                       'expected' => 'integer',
  1220.                       'paramnum' => 1));
  1221.  
  1222.         } elseif (($orient != HTML_PROGRESS2_BAR_HORIZONTAL) &&
  1223.                   ($orient != HTML_PROGRESS2_BAR_VERTICAL) &&
  1224.                   ($orient != HTML_PROGRESS2_POLYGONAL) &&
  1225.                   ($orient != HTML_PROGRESS2_CIRCLE)) {
  1226.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  1227.                 array('var' => '$orient',
  1228.                       'was' => $orient,
  1229.                       'expected' => HTML_PROGRESS2_BAR_HORIZONTAL.' | '.
  1230.                                     HTML_PROGRESS2_BAR_VERTICAL.' | '.
  1231.                                     HTML_PROGRESS2_POLYGONAL.' | '.
  1232.                                     HTML_PROGRESS2_CIRCLE,
  1233.                       'paramnum' => 1));
  1234.         }
  1235.  
  1236.         $previous = $this->orientation;    // gets previous orientation
  1237.         $this->orientation = $orient;      // sets the new orientation
  1238.  
  1239.         if ($previous != $orient) {
  1240.             // if orientation has changed, we need to swap cell width and height
  1241.             $w = $this->cell['width'];
  1242.             $h = $this->cell['height'];
  1243.  
  1244.             $this->cell['width']  = $h;
  1245.             $this->cell['height'] = $w;
  1246.  
  1247.             $this->_updateProgressSize();   // updates the new size of progress bar
  1248.         }
  1249.     }
  1250.  
  1251.     /**
  1252.      * Returns fill option of the progress meter.
  1253.      *
  1254.      * Get 'natural' or 'reverse', depending of the fill way of progress meter.
  1255.      * For horizontal progress bar, natural way is from left to right, and reverse
  1256.      * way is from right to left.
  1257.      * For vertical progress bar, natural way is from down to up, and reverse
  1258.      * way is from up to down.
  1259.      * The default fill way is 'natural'.
  1260.      *
  1261.      * @return     string
  1262.      * @since      2.0.0
  1263.      * @access     public
  1264.      * @see        setFillWay()
  1265.      */
  1266.     function getFillWay()
  1267.     {
  1268.         return $this->fillWay;
  1269.     }
  1270.  
  1271.     /**
  1272.      * Sets fill option of the progress meter.
  1273.      *
  1274.      * Sets the progress meter fill option: must be 'natural' or 'reverse'.
  1275.      * The default fill way is 'natural'.
  1276.      *
  1277.      * @param      string    $way           fill direction (natural or reverse)
  1278.      *
  1279.      * @return     void
  1280.      * @since      2.0.0
  1281.      * @access     public
  1282.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  1283.      * @see        getFillWay()
  1284.      */
  1285.     function setFillWay($way)
  1286.     {
  1287.         if (!is_string($way)) {
  1288.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  1289.                 array('var' => '$way',
  1290.                       'was' => gettype($way),
  1291.                       'expected' => 'string',
  1292.                       'paramnum' => 1));
  1293.  
  1294.         } elseif (($way != 'natural') && ($way != 'reverse')) {
  1295.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  1296.                 array('var' => '$way',
  1297.                       'was' => $way,
  1298.                       'expected' => 'natural | reverse',
  1299.                       'paramnum' => 1));
  1300.  
  1301.         }
  1302.         $this->fillWay = $way;
  1303.     }
  1304.  
  1305.     /**
  1306.      * Returns count of cell in the progress meter.
  1307.      *
  1308.      * Get the number of cell defined to a progress meter. It must be positive.
  1309.      * The default value is 10.
  1310.      *
  1311.      * @return     integer
  1312.      * @since      2.0.0
  1313.      * @access     public
  1314.      * @see        setCellCount()
  1315.      */
  1316.     function getCellCount()
  1317.     {
  1318.         return $this->cellCount;
  1319.     }
  1320.  
  1321.     /**
  1322.      * Sets count of cell in the progress meter.
  1323.      *
  1324.      * Defines the number of cell to a progress meter. It must be positive.
  1325.      * The default value is 10.
  1326.      *
  1327.      * @param      integer   $cells         Cell count on progress meter
  1328.      *
  1329.      * @return     void
  1330.      * @since      2.0.0
  1331.      * @access     public
  1332.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  1333.      * @see        getCellCount()
  1334.      */
  1335.     function setCellCount($cells)
  1336.     {
  1337.         if (!is_int($cells)) {
  1338.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  1339.                 array('var' => '$cells',
  1340.                       'was' => gettype($cells),
  1341.                       'expected' => 'integer',
  1342.                       'paramnum' => 1));
  1343.  
  1344.         } elseif ($cells < 0) {
  1345.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  1346.                 array('var' => '$cells',
  1347.                       'was' => $cells,
  1348.                       'expected' => 'greater or equal zero',
  1349.                       'paramnum' => 1));
  1350.         }
  1351.         $this->cellCount = $cells;
  1352.  
  1353.         $this->_updateProgressSize();   // updates the new size of progress bar
  1354.     }
  1355.  
  1356.     /**
  1357.      * Returns cell attributes values.
  1358.      *
  1359.      * Get all cell attributes in a associative array with key-value couple
  1360.      * (by default). Get the attributes as string is also possible.
  1361.      *
  1362.      * @param      bool      $asString      (optional) whether to return the attributes as string
  1363.      *
  1364.      * @return     mixed
  1365.      * @since      2.0.0
  1366.      * @access     public
  1367.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  1368.      * @see        setCellAttributes()
  1369.      */
  1370.     function getCellAttributes($asString = false)
  1371.     {
  1372.         if (!is_bool($asString)) {
  1373.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  1374.                 array('var' => '$asString',
  1375.                       'was' => gettype($asString),
  1376.                       'expected' => 'boolean',
  1377.                       'paramnum' => 1));
  1378.         }
  1379.  
  1380.         $attr = $this->cell;
  1381.  
  1382.         if ($asString) {
  1383.             return $this->_getAttrString($attr);
  1384.         } else {
  1385.             return $attr;
  1386.         }
  1387.     }
  1388.  
  1389.     /**
  1390.      * Sets cell attributes values.
  1391.      *
  1392.      * Sets cell attributes for all cells (default) or a specific an existing cell.
  1393.      *
  1394.      * Defaults are:
  1395.      *     <ul>
  1396.      *     <li>id             = pcel%01s
  1397.      *     <li>class          = cell
  1398.      *     <li>spacing        = 2
  1399.      *     <li>active-color   = #006600
  1400.      *     <li>inactive-color = #CCCCCC
  1401.      *     <li>font-family    = Courier, Verdana
  1402.      *     <li>font-size      = lowest value from cell width, cell height, and font size
  1403.      *     <li>color          = #000000
  1404.      *     <li>background-color    = #FFFFFF
  1405.      *     <li>background-image    = none
  1406.      *     <li>background-repeat   = no-repeat
  1407.      *     <li>background-position = top left
  1408.      *     <li>Horizontal Bar :
  1409.      *         <ul>
  1410.      *         <li>width      = 15
  1411.      *         <li>height     = 20
  1412.      *         </ul>
  1413.      *     <li>Vertical Bar :
  1414.      *         <ul>
  1415.      *         <li>width      = 20
  1416.      *         <li>height     = 15
  1417.      *         </ul>
  1418.      *     </ul>
  1419.      *
  1420.      * @param      mixed     $attributes    Associative array or string of HTML tag attributes
  1421.      * @param      int       $cell          (optional) Cell index
  1422.      *
  1423.      * @return     void
  1424.      * @since      2.0.0
  1425.      * @access     public
  1426.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  1427.      * @see        getCellAttributes()
  1428.      */
  1429.     function setCellAttributes($attributes, $cell = null)
  1430.     {
  1431.         if (!is_null($cell)) {
  1432.             if (!is_int($cell)) {
  1433.                 return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  1434.                     array('var' => '$cell',
  1435.                           'was' => gettype($cell),
  1436.                           'expected' => 'integer',
  1437.                           'paramnum' => 1));
  1438.  
  1439.             } elseif ($cell < 0) {
  1440.                 return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  1441.                     array('var' => '$cell',
  1442.                           'was' => $cell,
  1443.                           'expected' => 'positive',
  1444.                           'paramnum' => 1));
  1445.  
  1446.             } elseif ($cell > $this->cellCount) {
  1447.                 return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  1448.                     array('var' => '$cell',
  1449.                           'was' => $cell,
  1450.                           'expected' => 'less or equal '.$this->cellCount,
  1451.                           'paramnum' => 1));
  1452.             }
  1453.  
  1454.             $this->_updateAttrArray($this->cell[$cell], $this->_parseAttributes($attributes));
  1455.         } else {
  1456.             $this->_updateAttrArray($this->cell, $this->_parseAttributes($attributes));
  1457.         }
  1458.  
  1459.         $font_size   = $this->cell['font-size'];
  1460.         $cell_width  = $this->cell['width'];
  1461.         $cell_height = $this->cell['height'];
  1462.         $margin = ($this->orientation == HTML_PROGRESS2_BAR_HORIZONTAL) ? 0 : 3;
  1463.  
  1464.         $font_size = min(min($cell_width, $cell_height) - $margin, $font_size);
  1465.         $this->cell['font-size'] = $font_size;
  1466.  
  1467.         $this->_updateProgressSize();   // updates the new size of progress bar
  1468.     }
  1469.  
  1470.     /**
  1471.      * Returns coordinates of each cell for a polygonal progress meter.
  1472.      *
  1473.      * Get array of all cell coordinates (x,y) that define a polygonal
  1474.      * progress meter.
  1475.      * For example, a 3x3 square as: (0,0) for top left corner,
  1476.      * (2,0) for top right corner, (2,2) for bottom right corner, and
  1477.      * (0,2) for bottom left corner.
  1478.      *
  1479.      * @return     array
  1480.      * @since      2.0.0
  1481.      * @access     public
  1482.      * @see        setCellCoordinates()
  1483.      */
  1484.     function getCellCoordinates()
  1485.     {
  1486.         return isset($this->_coordinates) ? $this->_coordinates : array();
  1487.     }
  1488.  
  1489.     /**
  1490.      * Sets coordinates of each cell for a polygonal progress meter.
  1491.      *
  1492.      * A polygonal progress meter is defined by its size (width, height) and its
  1493.      * cells coordinates (array of couple x,y screen coordinates).
  1494.      *
  1495.      * @param      integer   $xgrid     The grid width in cell size
  1496.      * @param      integer   $ygrid     The grid height in cell size
  1497.      * @param      array     $coord     (optional) Coordinates (x,y) in the grid, of each cell
  1498.      *
  1499.      * @return     void
  1500.      * @since      2.0.0
  1501.      * @access     public
  1502.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  1503.      * @see        getCellCoordinates()
  1504.      */
  1505.     function setCellCoordinates($xgrid, $ygrid, $coord = array())
  1506.     {
  1507.         if (!is_int($xgrid)) {
  1508.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  1509.                 array('var' => '$xgrid',
  1510.                       'was' => gettype($xgrid),
  1511.                       'expected' => 'integer',
  1512.                       'paramnum' => 1));
  1513.  
  1514.         } elseif ($xgrid < 3) {
  1515.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  1516.                 array('var' => '$xgrid',
  1517.                       'was' => $xgrid,
  1518.                       'expected' => 'greater than 2',
  1519.                       'paramnum' => 1));
  1520.  
  1521.         } elseif (!is_int($ygrid)) {
  1522.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  1523.                 array('var' => '$ygrid',
  1524.                       'was' => gettype($ygrid),
  1525.                       'expected' => 'integer',
  1526.                       'paramnum' => 2));
  1527.  
  1528.         } elseif ($ygrid < 3) {
  1529.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  1530.                 array('var' => '$ygrid',
  1531.                       'was' => $ygrid,
  1532.                       'expected' => 'greater than 2',
  1533.                       'paramnum' => 2));
  1534.  
  1535.         } elseif (!is_array($coord)) {
  1536.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  1537.                 array('var' => '$coord',
  1538.                       'was' => gettype($coord),
  1539.                       'expected' => 'array',
  1540.                       'paramnum' => 3));
  1541.         }
  1542.  
  1543.         if (count($coord) == 0) {
  1544.             // Computes all coordinates of a standard polygon (square or rectangle)
  1545.             $coord = $this->_computeCoordinates($xgrid, $ygrid);
  1546.         } else {
  1547.             foreach ($coord as $id => $pos) {
  1548.                 if (!is_array($pos)) {
  1549.                     return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  1550.                         array('var' => '$coord[,$pos]',
  1551.                               'was' => gettype($pos),
  1552.                               'expected' => 'array',
  1553.                               'paramnum' => 3));
  1554.                 }
  1555.                 if ($pos[0] >= $ygrid) {
  1556.                     return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  1557.                         array('var' => '$pos[0]',
  1558.                               'was' => $pos[0],
  1559.                               'expected' => 'coordinate less than grid height',
  1560.                               'paramnum' => 2));
  1561.                 }
  1562.                 if ($pos[1] >= $xgrid) {
  1563.                     return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  1564.                         array('var' => '$pos[1]',
  1565.                               'was' => $pos[1],
  1566.                               'expected' => 'coordinate less than grid width',
  1567.                               'paramnum' => 1));
  1568.                 }
  1569.             }
  1570.         }
  1571.         $this->_coordinates = $coord;
  1572.         $this->_xgrid = $xgrid;
  1573.         $this->_ygrid = $ygrid;
  1574.  
  1575.         // auto-compute cell count
  1576.         $this->cellCount = count($coord);
  1577.  
  1578.         $this->_updateProgressSize();   // updates the new size of progress bar
  1579.     }
  1580.  
  1581.     /**
  1582.      * Returns progress bar's border attributes values.
  1583.      *
  1584.      * Get all border attributes in a associative array with key-value couple
  1585.      * (by default). Get the attributes as string is also possible.
  1586.      *
  1587.      * @param      bool      $asString      (optional) whether to return the attributes as string
  1588.      *
  1589.      * @return     mixed
  1590.      * @since      2.0.0
  1591.      * @access     public
  1592.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  1593.      * @see        setBorderAttributes()
  1594.      */
  1595.     function getBorderAttributes($asString = false)
  1596.     {
  1597.         if (!is_bool($asString)) {
  1598.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  1599.                 array('var' => '$asString',
  1600.                       'was' => gettype($asString),
  1601.                       'expected' => 'boolean',
  1602.                       'paramnum' => 1));
  1603.         }
  1604.  
  1605.         $attr = $this->border;
  1606.  
  1607.         if ($asString) {
  1608.             return $this->_getAttrString($attr);
  1609.         } else {
  1610.             return $attr;
  1611.         }
  1612.     }
  1613.  
  1614.     /**
  1615.      * Sets the progress bar's border attributes.
  1616.      *
  1617.      * Defines all border attributes (color, size, ...) a progress bar
  1618.      * (only horizontal or vertical) can handle.
  1619.      *
  1620.      * Defaults are:
  1621.      * <ul>
  1622.      * <li>class   = progressBorder%s
  1623.      * <li>width   = 0
  1624.      * <li>style   = solid
  1625.      * <li>color   = #000000
  1626.      * </ul>
  1627.      *
  1628.      * @param      mixed     $attributes    Associative array or string of HTML tag attributes
  1629.      *
  1630.      * @return     void
  1631.      * @since      2.0.0
  1632.      * @access     public
  1633.      * @see        getBorderAttributes()
  1634.      */
  1635.     function setBorderAttributes($attributes)
  1636.     {
  1637.         $this->_updateAttrArray($this->border, $this->_parseAttributes($attributes));
  1638.  
  1639.         $this->_updateProgressSize();   // updates the new size of progress bar
  1640.     }
  1641.  
  1642.     /**
  1643.      * Returns frame attributes values.
  1644.      *
  1645.      * Get all frame attributes in a associative array with key-value couple
  1646.      * (by default). Get the attributes as string is also possible.
  1647.      *
  1648.      * @param      bool      $asString      (optional) whether to return the attributes as string
  1649.      *
  1650.      * @return     mixed
  1651.      * @since      2.0.0
  1652.      * @access     public
  1653.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  1654.      * @see        setFrameAttributes()
  1655.      */
  1656.     function getFrameAttributes($asString = false)
  1657.     {
  1658.         if (!is_bool($asString)) {
  1659.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  1660.                 array('var' => '$asString',
  1661.                       'was' => gettype($asString),
  1662.                       'expected' => 'boolean',
  1663.                       'paramnum' => 1));
  1664.         }
  1665.  
  1666.         $attr = $this->frame;
  1667.  
  1668.         if ($asString) {
  1669.             return $this->_getAttrString($attr);
  1670.         } else {
  1671.             return $attr;
  1672.         }
  1673.     }
  1674.  
  1675.     /**
  1676.      * Sets the progress meter frame attributes.
  1677.      *
  1678.      * Allows to build a customisable frame (color, size) around the progress meter.
  1679.      *
  1680.      * Defaults are:
  1681.      * <ul>
  1682.      * <li>show          = true
  1683.      * <li>left          = 200
  1684.      * <li>top           = 100
  1685.      * <li>width         = 320
  1686.      * <li>height        = 90
  1687.      * <li>color         = #C0C0C0
  1688.      * <li>border-width  = 2
  1689.      * <li>border-style  = solid
  1690.      * <li>border-color  = #DFDFDF #404040 #404040 #DFDFDF
  1691.      * </ul>
  1692.      *
  1693.      * @param      null|array     $attributes    (optional) hash of style parameters
  1694.      *
  1695.      * @return     void
  1696.      * @since      2.0.0
  1697.      * @access     public
  1698.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT,
  1699.      *             HTML_PROGRESS2_ERROR_INVALID_OPTION
  1700.      */
  1701.     function setFrameAttributes($attributes = array())
  1702.     {
  1703.         if (!is_null($attributes) && !is_array($attributes)) {
  1704.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  1705.                 array('var' => '$attributes',
  1706.                       'was' => gettype($attributes),
  1707.                       'expected' => 'array',
  1708.                       'paramnum' => 1));
  1709.         }
  1710.  
  1711.         $default = array(
  1712.             'show' => true,
  1713.             'left' => 200,
  1714.             'top' => 100,
  1715.             'width' => 320,
  1716.             'height' => 90,
  1717.             'color' => '#C0C0C0',
  1718.             'border-width' => 2,
  1719.             'border-style' => 'solid',
  1720.             'border-color' => '#DFDFDF #404040 #404040 #DFDFDF'
  1721.         );
  1722.         $allowed_options = array_keys($default);
  1723.  
  1724.         $options = array_merge($default, $attributes);
  1725.  
  1726.         foreach ($options as $prop => $val) {
  1727.             if (in_array($prop, $allowed_options)) {
  1728.                 $this->frame[$prop] = $val;
  1729.             } else {
  1730.                 $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_OPTION, 'warning',
  1731.                     array('element' => 'frame', 'prop' => $prop)
  1732.                     );
  1733.             }
  1734.         }
  1735.     }
  1736.  
  1737.     /**
  1738.      * Returns attributes values of an existing label.
  1739.      *
  1740.      * Get all attributes of an existing label identified by $name argument.
  1741.      * This identifier must be the same as the one given to addLabel() method.
  1742.      * Return attributes values in a associative array with key-value couple
  1743.      * (by default). Get the attributes as string is also possible.
  1744.      *
  1745.      * @param      string    $name          progress label id.
  1746.      * @param      bool      $asString      (optional) whether to return the attributes as string
  1747.      *
  1748.      * @return     mixed
  1749.      * @since      2.0.0
  1750.      * @access     public
  1751.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  1752.      * @see        setLabelAttributes()
  1753.      */
  1754.     function getLabelAttributes($name, $asString = false)
  1755.     {
  1756.         if (!isset($this->label[$name])) {
  1757.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  1758.                 array('var' => '$name',
  1759.                       'was' => 'undefined',
  1760.                       'expected' => "label '$name' exists",
  1761.                       'paramnum' => 1));
  1762.  
  1763.         } elseif (!is_bool($asString)) {
  1764.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  1765.                 array('var' => '$asString',
  1766.                       'was' => gettype($asString),
  1767.                       'expected' => 'boolean',
  1768.                       'paramnum' => 2));
  1769.         }
  1770.  
  1771.         $attr = $this->label[$name];
  1772.  
  1773.         if ($asString) {
  1774.             return $this->_getAttrString($attr);
  1775.         } else {
  1776.             return $attr;
  1777.         }
  1778.     }
  1779.  
  1780.     /**
  1781.      * Sets attributes values of an existing label.
  1782.      *
  1783.      * Defines attributes (font, color, size, alignement ...) of an existing label.
  1784.      * Whether an attribute is not specified, previous or default value
  1785.      * is used instead.
  1786.      *
  1787.      * Defaults are:
  1788.      * <ul>
  1789.      * <li>class             = progressPercentLabel%s
  1790.      * <li>width             = 50
  1791.      * <li>height            = 0
  1792.      * <li>font-size         = 11
  1793.      * <li>font-family       = Verdana, Tahoma, Arial
  1794.      * <li>font-weight       = normal
  1795.      * <li>color             = #000000
  1796.      * <li>background-color  = transparent
  1797.      * <li>align             = right
  1798.      * <li>valign            = right
  1799.      * </ul>
  1800.      *
  1801.      * @param      string    $name          progress label id.
  1802.      * @param      mixed     $attributes    Associative array or string of HTML tag attributes
  1803.      *
  1804.      * @return     void
  1805.      * @since      2.0.0
  1806.      * @access     public
  1807.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  1808.      * @see        getLabelAttributes(), addLabel()
  1809.      */
  1810.     function setLabelAttributes($name, $attributes)
  1811.     {
  1812.         if (!isset($this->label[$name])) {
  1813.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  1814.                 array('var' => '$name',
  1815.                       'was' => "label '$name' undefined",
  1816.                       'expected' => 'label already exists',
  1817.                       'paramnum' => 1));
  1818.         }
  1819.  
  1820.         $this->_updateAttrArray($this->label[$name], $this->_parseAttributes($attributes));
  1821.  
  1822.         if ($this->label[$name]['type'] == HTML_PROGRESS2_LABEL_TEXT) {
  1823.             if ($this->_status != 'new') {
  1824.                 $this->_changeLabelText($name, $this->label[$name]['value']);
  1825.             }
  1826.         }
  1827.     }
  1828.  
  1829.     /**
  1830.      * Add a new label to the progress meter.
  1831.      *
  1832.      * Defines a new label identifier choosen between five categories:
  1833.      * <ul>
  1834.      * <li>HTML_PROGRESS2_LABEL_TEXT constant if you want a simple text zone
  1835.      * <li>HTML_PROGRESS2_LABEL_BUTTON constant if you want a form button
  1836.      * <li>HTML_PROGRESS2_LABEL_STEP constant if you want a step resume progress
  1837.      * <li>HTML_PROGRESS2_LABEL_PERCENT constant if you want current progress value
  1838.      * <li>HTML_PROGRESS2_LABEL_CROSSBAR constant if you want a little javascript animation
  1839.      * </ul>
  1840.      *
  1841.      * @param      string    $type          Label type (text,button,step,percent,crossbar)
  1842.      * @param      string    $name          Label name
  1843.      * @param      string    $value         (optional) default label value
  1844.      *
  1845.      * @return     void
  1846.      * @since      2.0.0
  1847.      * @access     public
  1848.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  1849.      * @see        setLabelAttributes(), removeLabel()
  1850.      */
  1851.     function addLabel($type, $name, $value = ' ')
  1852.     {
  1853.         if (($type != HTML_PROGRESS2_LABEL_TEXT) &&
  1854.             ($type != HTML_PROGRESS2_LABEL_BUTTON) &&
  1855.             ($type != HTML_PROGRESS2_LABEL_STEP) &&
  1856.             ($type != HTML_PROGRESS2_LABEL_PERCENT) &&
  1857.             ($type != HTML_PROGRESS2_LABEL_CROSSBAR)) {
  1858.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  1859.                 array('var' => '$type',
  1860.                       'was' => $type,
  1861.                       'expected' => 'HTML_PROGRESS2_LABEL_* constant value',
  1862.                       'paramnum' => 1));
  1863.  
  1864.         } elseif (!is_string($name)) {
  1865.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  1866.                 array('var' => '$name',
  1867.                       'was' => gettype($name),
  1868.                       'expected' => 'string',
  1869.                       'paramnum' => 2));
  1870.  
  1871.         } elseif (isset($this->label[$name])) {
  1872.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  1873.                 array('var' => '$name',
  1874.                       'was' => 'label already exists',
  1875.                       'expected' => "label '$name' undefined",
  1876.                       'paramnum' => 2));
  1877.  
  1878.         } elseif (!is_string($value)) {
  1879.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  1880.                 array('var' => '$value',
  1881.                       'was' => gettype($value),
  1882.                       'expected' => 'string',
  1883.                       'paramnum' => 3));
  1884.         }
  1885.  
  1886.         switch($type) {
  1887.         case HTML_PROGRESS2_LABEL_TEXT:
  1888.             $this->label[$name] = array(
  1889.                 'type' => $type,
  1890.                 'value' => $value,
  1891.                 'left' => 5,
  1892.                 'top' => 5,
  1893.                 'width' => 0,
  1894.                 'height' => 0,
  1895.                 'align' => 'left',
  1896.                 'valign' => 'top',
  1897.                 'background-color' => 'transparent',
  1898.                 'font-size' => 11,
  1899.                 'font-family' => 'Verdana, Tahoma, Arial',
  1900.                 'font-weight' => 'normal',
  1901.                 'color' => '#000000',
  1902.                 'class' => 'progressTextLabel%s'
  1903.             );
  1904.             break;
  1905.         case HTML_PROGRESS2_LABEL_BUTTON:
  1906.             $this->label[$name] = array(
  1907.                 'type' => $type,
  1908.                 'value' => $value,
  1909.                 'action' => '',
  1910.                 'target' => 'self',
  1911.                 'left' => 0,
  1912.                 'top' => 5,
  1913.                 'width' => 0,
  1914.                 'height' => 0,
  1915.                 'align' => 'center',
  1916.                 'valign' => 'bottom',
  1917.                 'background-color' => 'transparent',
  1918.                 'font-size' => 11,
  1919.                 'font-family' => 'Verdana, Tahoma, Arial',
  1920.                 'font-weight' => 'normal',
  1921.                 'color' => '#000000',
  1922.                 'class' => 'progressButtonLabel%s'
  1923.             );
  1924.             break;
  1925.         case HTML_PROGRESS2_LABEL_STEP:
  1926.             $this->label[$name] = array(
  1927.                 'type' => $type,
  1928.                 'value' => $value,
  1929.                 'left' => 5,
  1930.                 'top' => 5,
  1931.                 'width' => 165,
  1932.                 'height' => 0,
  1933.                 'align' => 'right',
  1934.                 'valign' => 'top',
  1935.                 'background-color' => 'transparent',
  1936.                 'font-size' => 11,
  1937.                 'font-family' => 'Verdana, Tahoma, Arial',
  1938.                 'font-weight' => 'normal',
  1939.                 'color' => '#000000',
  1940.                 'class' => 'progressStepLabel%s'
  1941.             );
  1942.             break;
  1943.         case HTML_PROGRESS2_LABEL_PERCENT:
  1944.             $this->label[$name] = array(
  1945.                 'type' => $type,
  1946.                 'value' => $value,
  1947.                 'left' => 5,
  1948.                 'top' => 5,
  1949.                 'width' => 50,
  1950.                 'height' => 0,
  1951.                 'align' => 'right',
  1952.                 'valign' => 'right',
  1953.                 'background-color' => 'transparent',
  1954.                 'font-size' => 11,
  1955.                 'font-family' => 'Verdana, Tahoma, Arial',
  1956.                 'font-weight' => 'normal',
  1957.                 'color' => '#000000',
  1958.                 'class' => 'progressPercentLabel%s'
  1959.             );
  1960.             break;
  1961.         case HTML_PROGRESS2_LABEL_CROSSBAR:
  1962.             $this->label[$name] = array(
  1963.                 'type' => $type,
  1964.                 'value' => $value,
  1965.                 'left' => 5,
  1966.                 'top' => 5,
  1967.                 'width' => 20,
  1968.                 'height' => 0,
  1969.                 'align' => 'center',
  1970.                 'valign' => 'top',
  1971.                 'background-color' => 'transparent',
  1972.                 'font-size' => 11,
  1973.                 'font-family' => 'Verdana, Tahoma, Arial',
  1974.                 'font-weight' => 'normal',
  1975.                 'color' => '#000000',
  1976.                 'class' => 'progressCrossbarLabel%s'
  1977.             );
  1978.             break;
  1979.         }
  1980.     }
  1981.  
  1982.     /**
  1983.      * Removes a label to the progress meter.
  1984.      *
  1985.      * The label identifier must exists or it cannot be remove. This is the same
  1986.      * identifier as the one given to addLabel() method.
  1987.      *
  1988.      * @param      string    $name          Label name
  1989.      *
  1990.      * @return     void
  1991.      * @since      2.0.0
  1992.      * @access     public
  1993.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  1994.      * @see        addLabel()
  1995.      */
  1996.     function removeLabel($name)
  1997.     {
  1998.         if (!is_string($name)) {
  1999.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  2000.                 array('var' => '$name',
  2001.                       'was' => gettype($name),
  2002.                       'expected' => 'string',
  2003.                       'paramnum' => 1));
  2004.  
  2005.         } elseif (!isset($this->label[$name])) {
  2006.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'notice',
  2007.                 array('var' => '$name',
  2008.                       'was' => 'label does not exists',
  2009.                       'expected' => "label '$name' defined",
  2010.                       'paramnum' => 1));
  2011.  
  2012.         }
  2013.  
  2014.         unset($this->label[$name]);
  2015.     }
  2016.  
  2017.     /**
  2018.      * Returns the progress background attributes values.
  2019.      *
  2020.      * Get all background attributes in a associative array with key-value couple
  2021.      * (by default). Get the attributes as string is also possible.
  2022.      *
  2023.      * @param      bool      $asString      (optional) whether to return the attributes as string
  2024.      *
  2025.      * @return     mixed
  2026.      * @since      2.0.0
  2027.      * @access     public
  2028.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  2029.      * @see        setProgressAttributes()
  2030.      */
  2031.     function getProgressAttributes($asString = false)
  2032.     {
  2033.         if (!is_bool($asString)) {
  2034.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  2035.                 array('var' => '$asString',
  2036.                       'was' => gettype($asString),
  2037.                       'expected' => 'boolean',
  2038.                       'paramnum' => 1));
  2039.         }
  2040.  
  2041.         $attr = $this->_progress;
  2042.  
  2043.         if ($asString) {
  2044.             return $this->_getAttrString($attr);
  2045.         } else {
  2046.             return $attr;
  2047.         }
  2048.     }
  2049.  
  2050.     /**
  2051.      * Sets the progress background attributes values.
  2052.      *
  2053.      * Background attributes are color and size, with default values:
  2054.      * <ul>
  2055.      * <li>background-color    = #FFFFFF
  2056.      * <li>background-image    = none
  2057.      * <li>background-repeat   = no-repeat
  2058.      * <li>background-position = top left
  2059.      * <li>Horizontal Bar :
  2060.      *     <ul>
  2061.      *     <li>width         = (cell_count * (cell_width + cell_spacing)) + cell_spacing
  2062.      *     <li>height        = cell_height + (2 * cell_spacing)
  2063.      *     </ul>
  2064.      * <li>Vertical Bar :
  2065.      *     <ul>
  2066.      *     <li>width         = cell_width + (2 * cell_spacing)
  2067.      *     <li>height        = (cell_count * (cell_height + cell_spacing)) + cell_spacing
  2068.      *     </ul>
  2069.      * </ul>
  2070.      *
  2071.      * @param      mixed     $attributes    Associative array or string of HTML tag attributes
  2072.      *
  2073.      * @return     void
  2074.      * @since      2.0.0
  2075.      * @access     public
  2076.      * @see        getProgressAttributes()
  2077.      */
  2078.     function setProgressAttributes($attributes)
  2079.     {
  2080.         $this->_updateAttrArray($this->_progress, $this->_parseAttributes($attributes));
  2081.     }
  2082.  
  2083.     /**
  2084.      * Returns javascript progress meter handler.
  2085.      *
  2086.      * Get the javascript URL or inline code that will handle the progress meter
  2087.      * refresh.
  2088.      *
  2089.      * @param      boolean   $raw           (optional) html output with script tags or just raw data
  2090.      *
  2091.      * @return     string
  2092.      * @since      2.0.0
  2093.      * @access     public
  2094.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  2095.      * @see        setScript()
  2096.      */
  2097.     function getScript($raw = true)
  2098.     {
  2099.         if (!is_bool($raw)) {
  2100.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  2101.                 array('var' => '$raw',
  2102.                       'was' => gettype($raw),
  2103.                       'expected' => 'boolean',
  2104.                       'paramnum' => 1));
  2105.         }
  2106.  
  2107.         if (!is_null($this->script)) {
  2108.  
  2109.             if ($raw) {
  2110.                 $js = $this->script;   // URL to the linked Progress JavaScript
  2111.             } else {
  2112.                 $js = '<script type="text/javascript" src="' . $this->script
  2113.                     . '"></script>' . PHP_EOL;
  2114.             }
  2115.             return $js;
  2116.         }
  2117.  
  2118.         $js = <<< JS
  2119.  
  2120. function setProgress(pIdent, pValue, pDeterminate, pCellCount)
  2121. {
  2122.     if (pValue == pDeterminate) {
  2123.         for (var i = 0; i < pCellCount; i++) {
  2124.             showCell(i, pIdent, 'I');
  2125.         }
  2126.     }
  2127.     if ((pDeterminate > 0) && (pValue > 0)) {
  2128.         var i = (pValue - 1) % pCellCount;
  2129.         showCell(i, pIdent, 'A');
  2130.     } else {
  2131.         for (var i = pValue - 1; i >= 0; i--) {
  2132.             showCell(i, pIdent, 'A');
  2133.         }
  2134.     }
  2135. }
  2136.  
  2137. function showCell(pCell, pIdent, pVisibility)
  2138. {
  2139.     var name = '%progressCell%' + pCell + pIdent;
  2140.     var cellElement = document.getElementById(name);
  2141.     cellElement.className = '%cellCN%' + pIdent + pVisibility;
  2142. }
  2143.  
  2144. function hideProgress(pIdent)
  2145. {
  2146.     var name = 'tfrm' + pIdent;
  2147.     var tfrm = document.getElementById(name);
  2148.     tfrm.style.visibility = "hidden";
  2149. }
  2150.  
  2151. function setLabelText(pIdent, pName, pText)
  2152. {
  2153.     var name = 'plbl' + pName + pIdent;
  2154.     document.getElementById(name).firstChild.nodeValue = pText;
  2155. }
  2156.  
  2157. function setElementStyle(pPrefix, pName, pIdent, pStyles)
  2158. {
  2159.     var name = pPrefix + pName + pIdent;
  2160.     var styles = pStyles.split(';');
  2161.     styles.pop();
  2162.     for (var i = 0; i < styles.length; i++) {
  2163.         var s = styles[i].split(':');
  2164.         var c = 'document.getElementById(name).style.' + s[0] + '="' + s[1] + '"';
  2165.         eval(c);
  2166.     }
  2167. }
  2168.  
  2169. function setRotaryCross(pIdent, pName)
  2170. {
  2171.     var name = 'plbl' + pName + pIdent;
  2172.     var cross = document.getElementById(name).firstChild.nodeValue;
  2173.     switch(cross) {
  2174.         case "--": cross = "\\\\"; break;
  2175.         case "\\\\": cross = "|"; break;
  2176.         case "|": cross = "/"; break;
  2177.         default: cross = "--"; break;
  2178.     }
  2179.     document.getElementById(name).firstChild.nodeValue = cross;
  2180. }
  2181.  
  2182. JS;
  2183.         $cellAttr = $this->getCellAttributes();
  2184.         $attr = array(
  2185.             trim(sprintf($cellAttr['id'], '   ')),
  2186.             trim(sprintf($cellAttr['class'], ' '))
  2187.             );
  2188.         $js = str_replace(array('%progressCell%', '%cellCN%'), $attr, $js);
  2189.  
  2190.         if ($raw !== true) {
  2191.             $js = '<script type="text/javascript">' . PHP_EOL
  2192.                 . '//<![CDATA[' . $js . '//]]>'     . PHP_EOL
  2193.                 . '</script>'                       . PHP_EOL;
  2194.         }
  2195.         return $js;
  2196.     }
  2197.  
  2198.     /**
  2199.      * Sets the javascript progress meter handler.
  2200.      *
  2201.      * Defines the javascript source (URL or inline code) that will handle
  2202.      * the progress meter refresh.
  2203.      *
  2204.      * @param      string    $url           URL to the linked Progress JavaScript
  2205.      *
  2206.      * @return     void
  2207.      * @since      2.0.0
  2208.      * @access     public
  2209.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  2210.      * @see        getScript()
  2211.      */
  2212.     function setScript($url)
  2213.     {
  2214.         if (!is_null($url)) {
  2215.             if (!is_string($url)) {
  2216.                 return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  2217.                     array('var' => '$url',
  2218.                           'was' => gettype($url),
  2219.                           'expected' => 'string',
  2220.                           'paramnum' => 1));
  2221.  
  2222.             } elseif (!is_file($url) || $url == '.' || $url == '..') {
  2223.                 return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  2224.                     array('var' => '$url',
  2225.                           'was' => $url.' file does not exists',
  2226.                           'expected' => 'javascript file exists',
  2227.                           'paramnum' => 1));
  2228.             }
  2229.         }
  2230.  
  2231.         /*
  2232.          - since version 0.5.0,
  2233.          - default javascript code comes from getScript() method
  2234.          - but may be overrided by external file.
  2235.         */
  2236.         $this->script = $url;
  2237.     }
  2238.  
  2239.     /**
  2240.      * Draw all circle segment pictures.
  2241.      *
  2242.      * This function build/prepare all circle segment PNG pictures that will be
  2243.      * send to browser output. Requires PEAR::Image_Color and PHP:gd extension.
  2244.      *
  2245.      * @param      string    $dir           (optional) Directory where pictures should be created
  2246.      * @param      string    $fileMask      (optional) sprintf format for pictures filename
  2247.      *
  2248.      * @return     array
  2249.      * @since      2.0.0
  2250.      * @access     public
  2251.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  2252.      * @see        setCellAttributes()
  2253.      */
  2254.     function drawCircleSegments($dir = '.', $fileMask = 'c%s.png')
  2255.     {
  2256.         if (!is_dir($dir)) {
  2257.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  2258.                 array('var' => '$dir',
  2259.                       'was' => $dir,
  2260.                       'expected' => 'directory exists',
  2261.                       'paramnum' => 1));
  2262.         }
  2263.  
  2264.         require_once 'Image/Color.php';
  2265.  
  2266.         $cellAttr  = $this->getCellAttributes();
  2267.         $w = $cellAttr['width'];
  2268.         $h = $cellAttr['height'];
  2269.         $s = $cellAttr['spacing'];
  2270.         $c = intval(360 / $this->cellCount);
  2271.         if (fmod($w,2) == 0) {
  2272.             $cx = floor($w / 2) - 0.5;
  2273.         } else {
  2274.             $cx = floor($w / 2);
  2275.         }
  2276.         if (fmod($h,2) == 0) {
  2277.             $cy = floor($h / 2) - 0.5;
  2278.         } else {
  2279.             $cy = floor($h / 2);
  2280.         }
  2281.  
  2282.         $image = imagecreate($w, $h);
  2283.  
  2284.         $bg     = Image_Color::allocateColor($image, $cellAttr['background-color']);
  2285.         $colorA = Image_Color::allocateColor($image, $cellAttr['active-color']);
  2286.         $colorI = Image_Color::allocateColor($image, $cellAttr['inactive-color']);
  2287.  
  2288.         imagefilledarc($image, $cx, $cy, $w, $h, 0, 360, $colorI, IMG_ARC_EDGED);
  2289.         $filename = $dir . DIRECTORY_SEPARATOR . sprintf($fileMask,0);
  2290.         imagepng($image, $filename);
  2291.         $this->setCellAttributes(array('background-image' => $filename),0);
  2292.  
  2293.         for ($i = 0; $i < $this->cellCount; $i++) {
  2294.             if ($this->fillWay == 'natural') {
  2295.                 $sA = $i*$c;
  2296.                 $eA = ($i+1)*$c;
  2297.                 $sI = ($i+1)*$c;
  2298.                 $eI = 360;
  2299.             } else {
  2300.                 $sA = 360-(($i+1)*$c);
  2301.                 $eA = 360-($i*$c);
  2302.                 $sI = 0;
  2303.                 $eI = 360-(($i+1)*$c);
  2304.             }
  2305.             if ($s > 0) {
  2306.                 imagefilledarc($image, $cx, $cy, $w, $h, 0, $sA, $colorI, IMG_ARC_EDGED);
  2307.             }
  2308.             imagefilledarc($image, $cx, $cy, $w, $h, $sA, $eA, $colorA, IMG_ARC_EDGED);
  2309.             imagefilledarc($image, $cx, $cy, $w, $h, $sI, $eI, $colorI, IMG_ARC_EDGED);
  2310.             $filename = $dir . DIRECTORY_SEPARATOR . sprintf($fileMask,$i+1);
  2311.             imagepng($image, $filename);
  2312.  
  2313.             $this->setCellAttributes(array('background-image' => $filename),$i+1);
  2314.         }
  2315.         imagedestroy($image);
  2316.     }
  2317.  
  2318.     /**
  2319.      * Returns delay execution of the progress meter.
  2320.      *
  2321.      * Given a delay in process of the progress meter is only necessary
  2322.      * if you need demonstration or also smooth animation.
  2323.      * The default value is zero (no delay).
  2324.      *
  2325.      * @return     integer
  2326.      * @since      2.0.0
  2327.      * @access     public
  2328.      * @see        setAnimSpeed()
  2329.      */
  2330.     function getAnimSpeed()
  2331.     {
  2332.         return $this->animSpeed;
  2333.     }
  2334.  
  2335.     /**
  2336.      * Sets delay execution of the progress meter.
  2337.      *
  2338.      * The delay (in milisecond) cannot exceed 1000 (1 second), that is enough
  2339.      * to smooth an animation. User process should slow down animation and in most
  2340.      * case the default value (zero) will be efficient.
  2341.      *
  2342.      * @param      integer   $delay         Delay in milisecond.
  2343.      *
  2344.      * @return     void
  2345.      * @since      2.0.0
  2346.      * @access     public
  2347.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  2348.      * @see        getAnimSpeed()
  2349.      */
  2350.     function setAnimSpeed($delay)
  2351.     {
  2352.         if (!is_int($delay)) {
  2353.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  2354.                 array('var' => '$delay',
  2355.                       'was' => gettype($delay),
  2356.                       'expected' => 'integer',
  2357.                       'paramnum' => 1));
  2358.  
  2359.         } elseif ($delay < 0) {
  2360.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  2361.                 array('var' => '$delay',
  2362.                       'was' => $delay,
  2363.                       'expected' => 'greater than zero',
  2364.                       'paramnum' => 1));
  2365.  
  2366.         } elseif ($delay > 1000) {
  2367.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  2368.                 array('var' => '$delay',
  2369.                       'was' => $delay,
  2370.                       'expected' => 'less or equal 1000',
  2371.                       'paramnum' => 1));
  2372.         }
  2373.         $this->animSpeed = $delay;
  2374.     }
  2375.  
  2376.     /**
  2377.      * Returns the cascading style sheet (CSS).
  2378.      *
  2379.      * Get the CSS required to display the progress meter in a HTML document.
  2380.      *
  2381.      * @param      boolean   $raw           (optional) html output with script tags or just raw data
  2382.      *
  2383.      * @return     string
  2384.      * @since      2.0.0
  2385.      * @access     public
  2386.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  2387.      */
  2388.     function getStyle($raw = true)
  2389.     {
  2390.         if (!is_bool($raw)) {
  2391.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  2392.                 array('var' => '$raw',
  2393.                       'was' => gettype($raw),
  2394.                       'expected' => 'boolean',
  2395.                       'paramnum' => 1));
  2396.         }
  2397.  
  2398.         $progressAttr = $this->getProgressAttributes();
  2399.         $borderAttr = $this->getBorderAttributes();
  2400.         $cellAttr = $this->getCellAttributes();
  2401.  
  2402.         $css = new HTML_CSS();
  2403.  
  2404.         $borderCls = '.' . sprintf($borderAttr['class'], $this->ident);
  2405.         $css->setStyle($borderCls, 'width', $progressAttr['width'].'px');
  2406.         $css->setStyle($borderCls, 'height', $progressAttr['height'].'px');
  2407.         if ($this->isBorderPainted()) {
  2408.             $css->setStyle($borderCls, 'border-width', $borderAttr['width'].'px');
  2409.             $css->setStyle($borderCls, 'border-style', $borderAttr['style']);
  2410.             $css->setStyle($borderCls, 'border-color', $borderAttr['color']);
  2411.         }
  2412.         if ($progressAttr['background-image'] !== 'none') {
  2413.             $css->setStyle($borderCls, 'background-image', 'url("'. $progressAttr['background-image'] .'")');
  2414.             $css->setStyle($borderCls, 'background-repeat', $progressAttr['background-repeat']);
  2415.             $css->setStyle($borderCls, 'background-position', $progressAttr['background-position']);
  2416.         }
  2417.         if ($this->cellCount > 0) {
  2418.             $css->setStyle($borderCls, 'background-color', $progressAttr['background-color']);
  2419.         } else {
  2420.             $css->setStyle($borderCls, 'background-color', $cellAttr['inactive-color']);
  2421.         }
  2422.  
  2423.         foreach($this->label as $name => $data) {
  2424.             $style = '.' . sprintf($data['class'], $name . $this->ident);
  2425.  
  2426.             if ($data['width'] > 0) {
  2427.                 $css->setStyle($style, 'width', $data['width'].'px');
  2428.             }
  2429.             if ($data['height'] > 0) {
  2430.                 $css->setStyle($style, 'height', $data['height'].'px');
  2431.             }
  2432.             $css->setStyle($style, 'text-align', $data['align']);
  2433.             $css->setStyle($style, 'background-color', $data['background-color']);
  2434.             $css->setStyle($style, 'font-size', $data['font-size'].'px');
  2435.             $css->setStyle($style, 'font-family', $data['font-family']);
  2436.             $css->setStyle($style, 'font-weight', $data['font-weight']);
  2437.             $css->setStyle($style, 'color', $data['color']);
  2438.         }
  2439.  
  2440.         $cellClsI = '.' . sprintf($cellAttr['class'], $this->ident) . 'I';
  2441.         $cellClsA = '.' . sprintf($cellAttr['class'], $this->ident) . 'A';
  2442.         $css->setStyle($cellClsI, 'width', $cellAttr['width'].'px');
  2443.         $css->setStyle($cellClsI, 'height', $cellAttr['height'].'px');
  2444.         $css->setStyle($cellClsI, 'font-family', $cellAttr['font-family']);
  2445.         $css->setStyle($cellClsI, 'font-size', $cellAttr['font-size'].'px');
  2446.  
  2447.         if ($this->orientation == HTML_PROGRESS2_BAR_HORIZONTAL) {
  2448.             $css->setStyle($cellClsI, 'float', 'left');
  2449.         }
  2450.         if ($this->orientation == HTML_PROGRESS2_BAR_VERTICAL) {
  2451.             $css->setStyle($cellClsI, 'float', 'none');
  2452.         }
  2453.         $css->setSameStyle($cellClsA, $cellClsI);
  2454.  
  2455.         if ($this->orientation !== HTML_PROGRESS2_CIRCLE) {
  2456.             $css->setStyle($cellClsI, 'background-color', $cellAttr['inactive-color']);
  2457.         }
  2458.  
  2459.         $css->setStyle($cellClsA, 'background-color', $cellAttr['active-color']);
  2460.         if ($cellAttr['background-image'] !== 'none') {
  2461.             $css->setStyle($cellClsA, 'background-image', 'url("'. $cellAttr['background-image'] .'")');
  2462.             if ($this->orientation == HTML_PROGRESS2_CIRCLE) {
  2463.                 $css->setStyle($cellClsA, 'background-repeat', 'no-repeat');
  2464.             } else {
  2465.                 $css->setStyle($cellClsA, 'background-repeat', $cellAttr['background-repeat']);
  2466.                 $css->setStyle($cellClsA, 'background-position', $cellAttr['background-position']);
  2467.             }
  2468.         }
  2469.  
  2470.         if ($this->orientation == HTML_PROGRESS2_CIRCLE) {
  2471.             $css->setStyle($cellClsI, 'background-image', 'url("'.$cellAttr[0]['background-image'].'")');
  2472.             $css->setStyle($cellClsI, 'background-repeat', 'no-repeat');
  2473.         }
  2474.         $styles = $css->toString();
  2475.  
  2476.         if ($raw !== true) {
  2477.             $styles = '<style type="text/css">' . PHP_EOL
  2478.                     . '<!--'    . PHP_EOL
  2479.                     . $styles   . PHP_EOL
  2480.                     . ' -->'    . PHP_EOL
  2481.                     . '</style>'. PHP_EOL;
  2482.         }
  2483.         return $styles;
  2484.     }
  2485.  
  2486.     /**
  2487.      * Import cascading style sheet (CSS) elements
  2488.      *
  2489.      * Set the CSS required to display the progress meter in a HTML document.
  2490.      *
  2491.      * @param      mixed     $styles        CSS elements reference to import
  2492.      *
  2493.      * @return     void|PEAR_Error
  2494.      * @since      2.2.0
  2495.      * @access     public
  2496.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  2497.      */
  2498.     function importStyle($styles)
  2499.     {
  2500.         if (is_string($styles)) {
  2501.             $styles = (array)$styles;
  2502.         }
  2503.  
  2504.         if (!is_array($styles)) {
  2505.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  2506.                 array('var' => '$styles',
  2507.                       'was' => gettype($styles),
  2508.                       'expected' => 'array | string',
  2509.                       'paramnum' => 1));
  2510.         }
  2511.  
  2512.         $css = new HTML_CSS();
  2513.  
  2514.         $res = $css->parseData($styles);
  2515.         if ($css->isError()) {
  2516.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  2517.                 array('var' => '$styles',
  2518.                       'was' => 'unknown data source',
  2519.                       'expected' => 'valid CSS',
  2520.                       'paramnum' => 1));
  2521.         }
  2522.  
  2523.         if (strpos($this->border['class'], '%s') === false) {
  2524.             $pattern = $this->ident . '\.' . $this->border['class'];
  2525.         } else {
  2526.             $pattern = '\.' . sprintf($this->border['class'], $this->ident);
  2527.         }
  2528.         $border = $css->grepStyle("/$pattern/");
  2529.  
  2530.         foreach ($border as $b) {
  2531.             foreach ($b as $p => $v) {
  2532.                 if (substr($p, 0, 6) == 'border') {
  2533.                     $n = str_replace('border-', '', $p);
  2534.                     if (isset($this->border[$n])) {
  2535.                         if (substr($v, -2) == 'px') {
  2536.                             $this->border[$n] = intval($v);
  2537.                         } else {
  2538.                             $this->border[$n] = $v;
  2539.                         }
  2540.                     }
  2541.                 } else {
  2542.                     if ($p == 'background-color' && $this->cellCount == 0) {
  2543.                         $this->cell['inactive-color'] = $v;
  2544.                     } elseif (isset($this->_progress[$p])) {
  2545.                         if (substr($v, -2) == 'px') {
  2546.                             $this->_progress[$p] = intval($v);
  2547.                         } else {
  2548.                             $this->_progress[$p] = $v;
  2549.                         }
  2550.                     }
  2551.                 }
  2552.             }
  2553.             if ($this->border['width'] > 0) {
  2554.                 $this->_paintBorder = true;
  2555.             }
  2556.         }
  2557.  
  2558.         foreach ($this->label as $name => $data) {
  2559.             if (strpos($data['class'], '%s') === false) {
  2560.                 $pattern = $name . $this->ident . '\.' . $data['class'];
  2561.             } else {
  2562.                 $pattern = '\.' . sprintf($data['class'], $name . $this->ident);
  2563.             }
  2564.             $label = $css->grepStyle("/$pattern/");
  2565.  
  2566.             foreach ($label as $l) {
  2567.                 foreach ($l as $p => $v) {
  2568.                     if (substr($p, 0, 4) == 'text') {
  2569.                         $n = str_replace('text-', '', $p);
  2570.                         if (isset($this->label[$name][$n])) {
  2571.                             $this->label[$name][$n] = $v;
  2572.                         }
  2573.                     } elseif (isset($this->label[$name][$p])) {
  2574.                         if (substr($v, -2) == 'px') {
  2575.                             $this->label[$name][$p] = intval($v);
  2576.                         } else {
  2577.                             $this->label[$name][$p] = $v;
  2578.                         }
  2579.                     }
  2580.                 }
  2581.             }
  2582.         }
  2583.  
  2584.         $pcell = '.' . sprintf($this->cell['class'], $this->ident);
  2585.         if (strpos($this->cell['class'], '%s') === false) {
  2586.             $pattern = $this->ident . '\s*\.' . $this->cell['class'];
  2587.         } else {
  2588.             $pattern = '\.' . sprintf($this->cell['class'], $this->ident);
  2589.         }
  2590.         $cell = $css->grepStyle("/$pattern/");
  2591.  
  2592.         foreach ($cell as $c => $data) {
  2593.             foreach ($data as $p => $v) {
  2594.                 if ($p == 'background-color') {
  2595.                     if (strpos($c, $pcell.'A') !== false) {
  2596.                         $this->cell['active-color'] = $v;
  2597.                     } else {
  2598.                         $this->cell['inactive-color'] = $v;
  2599.                     }
  2600.                 } elseif ($p == 'background-image') {
  2601.                     $pattern = "\s*url\s*\([\s\"'`]*([\w:?=@&\/#._;-]+)[\s\"'`]*\)\s*";
  2602.                     $found = preg_match("/$pattern/", $v, $matches);
  2603.                     if ($found) {
  2604.                         $this->cell[$p] = $matches[1];
  2605.                     }
  2606.                 } else {
  2607.                     if (substr($v, -2) == 'px') {
  2608.                         $this->cell[$p] = intval($v);
  2609.                     } else {
  2610.                         $this->cell[$p] = $v;
  2611.                     }
  2612.                 }
  2613.             }
  2614.         }
  2615.     }
  2616.  
  2617.     /**
  2618.      * Returns the progress meter structure into an array.
  2619.      *
  2620.      * Get all progress meter properties, couple key-value, into a php array.
  2621.      * This structure is read-only, a dump-like information.
  2622.      *
  2623.      * @return     array
  2624.      * @since      2.0.0
  2625.      * @access     public
  2626.      */
  2627.     function toArray()
  2628.     {
  2629.         $structure = array(
  2630.             'id' => $this->ident,
  2631.             'indeterminate' => $this->indeterminate,
  2632.             'borderpainted' => $this->isBorderPainted(),
  2633.             'label' => $this->label,
  2634.             'animspeed' => $this->animSpeed,
  2635.             'orientation' => $this->orientation,
  2636.             'fillway' => $this->fillWay,
  2637.             'cell' => $this->cell,
  2638.             'cellcount' => $this->cellCount,
  2639.             'cellcoord' => $this->getCellCoordinates(),
  2640.             'border' => $this->border,
  2641.             'progress' => $this->_progress,
  2642.             'script' => $this->getScript(),
  2643.             'minimum' => $this->minimum,
  2644.             'maximum' => $this->maximum,
  2645.             'increment' => $this->increment,
  2646.             'value' => $this->value,
  2647.             'percent' => $this->getPercentComplete()
  2648.         );
  2649.         return $structure;
  2650.     }
  2651.  
  2652.     /**
  2653.      * Returns the progress meter structure as HTML.
  2654.      *
  2655.      * Get html code required to display the progress meter in any html document.
  2656.      *
  2657.      * @return     string
  2658.      * @since      2.0.0
  2659.      * @access     public
  2660.      */
  2661.     function toHtml()
  2662.     {
  2663.         $strHtml = '';
  2664.         $tabs = $this->_getTabs();
  2665.         $tab = $this->_getTab();
  2666.         $comment = $this->getComment();
  2667.         $progressAttr = $this->getProgressAttributes();
  2668.         $borderAttr = $this->getBorderAttributes();
  2669.         $cellAttr = $this->getCellAttributes();
  2670.  
  2671.         /**
  2672.          *  Adds a progress meter caption in html code is possible.
  2673.          *  See HTML_Common::setComment() method.
  2674.          */
  2675.         if (strlen($comment) > 0) {
  2676.             $strHtml .= $tabs . "<!-- $comment -->" . PHP_EOL;
  2677.         }
  2678.  
  2679.         //  Start of Top progress meter frame
  2680.         if ($this->frame['show']) {
  2681.             $topshift = $progressAttr['top'];
  2682.             $leftshift = $progressAttr['left'];
  2683.             $border = '';
  2684.             if ($this->frame['border-width'] > 0) {
  2685.                 $border = 'border-width:' . $this->frame['border-width'] . 'px;'
  2686.                         . 'border-style:' . $this->frame['border-style'] . ';'
  2687.                         . 'border-color:' . $this->frame['border-color'] . ';';
  2688.             }
  2689.             if ($progressAttr['position'] == 'relative') {
  2690.                 $_top = $_left = 0;
  2691.             } else {
  2692.                 $_top = $this->frame['top'];
  2693.                 $_left = $this->frame['left'];
  2694.             }
  2695.             $strHtml .= $tabs
  2696.                   .  '<div id="tfrm' . $this->ident . '" style="'
  2697.                   .  'position:' . $progressAttr['position'] . ';'
  2698.                   .  'top:' . $_top . 'px;'
  2699.                   .  'left:' . $_left . 'px;'
  2700.                   .  'width:' . $this->frame['width'] . 'px;'
  2701.                   .  'height:' . $this->frame['height'] . 'px;'
  2702.                   .  $border
  2703.                   .  'background-color:' . $this->frame['color'] . ';">'
  2704.                   .  PHP_EOL;
  2705.  
  2706.         } else {
  2707.             $topshift = $leftshift = 0;
  2708.             $strHtml .= $tabs
  2709.                  .  '<div id="tfrm' . $this->ident . '" style="'
  2710.                  .  'position:' . $progressAttr['position'] . ';'
  2711.                  .  'top:' . $progressAttr['top'] . 'px;'
  2712.                  .  'left:' . $progressAttr['left'] . 'px;'
  2713.                  .  'height:{_heightshift_}px;">'
  2714.                  .  PHP_EOL;
  2715.         }
  2716.  
  2717.         //  Start of progress meter border
  2718.         $strHtml .= $tabs
  2719.                  .  '<div id="pbrd' . $this->ident . '"'
  2720.                  .  ' style="position:absolute;top:{_topshift_}px;left:{_leftshift_}px;"'
  2721.                  .  ' class="' . sprintf($borderAttr['class'], $this->ident) . '">'
  2722.                  .  PHP_EOL;
  2723.  
  2724.         //  Start of progress meter
  2725.         if ($this->cellCount == 0) {
  2726.             $strHtml .= $tabs
  2727.                      .  '<div id="pbar' . $this->ident . '" style="'
  2728.                      .  'width:' . $progressAttr['width'] . 'px;'
  2729.                      .  'height:' . $progressAttr['height'] . 'px;'
  2730.                      .  'background-color:' . $cellAttr['active-color'] . ';">'
  2731.                      .  PHP_EOL;
  2732.         } else {
  2733.             $strHtml .= $tabs
  2734.                      .  '<div id="pbar' . $this->ident . '">'
  2735.                      .  PHP_EOL;
  2736.         }
  2737.  
  2738.         if ($this->orientation == HTML_PROGRESS2_BAR_HORIZONTAL) {
  2739.             $progressHtml = $this->_getProgressHbar_toHtml();
  2740.         }
  2741.         if ($this->orientation == HTML_PROGRESS2_BAR_VERTICAL) {
  2742.             $progressHtml = $this->_getProgressVbar_toHtml();
  2743.         }
  2744.         if ($this->orientation == HTML_PROGRESS2_POLYGONAL) {
  2745.             $progressHtml = $this->_getProgressPolygonal_toHtml();
  2746.         }
  2747.         if ($this->orientation == HTML_PROGRESS2_CIRCLE) {
  2748.             $cellAttr = $this->getCellAttributes();
  2749.             if (!isset($cellAttr[0]['background-image']) || !file_exists($cellAttr[0]['background-image'])) {
  2750.                 // creates default circle segments pictures :
  2751.                 // 'c0.png'->0% 'c1.png'->10%, 'c2.png'->20%, ... 'c10.png'->100%
  2752.                 $this->drawCircleSegments();
  2753.             }
  2754.             $progressHtml = $this->_getProgressCircle_toHtml();
  2755.         }
  2756.  
  2757.         $strHtml .= $tabs
  2758.                  .  $progressHtml
  2759.                  .  PHP_EOL;
  2760.  
  2761.         //  Enf of progress meter
  2762.         $strHtml .= $tabs
  2763.                  .  '</div>'
  2764.                  .  PHP_EOL;
  2765.  
  2766.         //  Enf of progress meter border
  2767.         $strHtml .= $tabs
  2768.                  .  '</div>'
  2769.                  .  PHP_EOL;
  2770.  
  2771.         $cyshift = 0;
  2772.         $heightshift = $progressAttr['height'];
  2773.  
  2774.         //  Start of progress meter labels
  2775.         foreach ($this->label as $name => $data) {
  2776.  
  2777.             $align = $data['align'];
  2778.             $width = $data['width'];
  2779.             $height = $data['height'];
  2780.  
  2781.             if ($progressAttr['position'] == 'relative') {
  2782.                 switch ($data['valign']) {
  2783.                     case 'top':
  2784.                         $style_pos = 'top:0;left:{_leftshift_}px;';
  2785.                         if ($data['height'] > 0) {
  2786.                             $topshift = $data['height'];
  2787.                         } else {
  2788.                             $topshift = $progressAttr['height'];
  2789.                         }
  2790.                         $height = $topshift;
  2791.                         $heightshift += $height;
  2792.                         break;
  2793.                     case 'right':
  2794.                         $style_pos = 'top:{_topshift_}px;'
  2795.                                    . 'left:{_rxshift_}px;';
  2796.                         break;
  2797.                     case 'bottom':
  2798.                         $style_pos = 'top:{_cyshift_}px;'
  2799.                                    . 'left:{_leftshift_}px;';
  2800.                         $cyshift = $progressAttr['height'];
  2801.                         if ($data['height'] == 0) {
  2802.                             $height = $progressAttr['height'];
  2803.                         }
  2804.                         $heightshift += $height;
  2805.                         break;
  2806.                     case 'left':
  2807.                         $style_pos = 'top:{_topshift_}px;left:0;';
  2808.                         if ($data['width'] > 0) {
  2809.                             $leftshift = $data['width'];
  2810.                         } else {
  2811.                             $leftshift = $progressAttr['width'];
  2812.                         }
  2813.                         $leftshift += $data['left'];
  2814.                         break;
  2815.                     case 'center':
  2816.                         $style_pos = 'top:{_cyshift_}px;'
  2817.                                    . 'left:{_leftshift_}px;';
  2818.                         $cyshift = intval($progressAttr['height']) / 2;
  2819.                         $width = $progressAttr['width'];
  2820.                         $align = 'center';
  2821.                         break;
  2822.                 }
  2823.                 if ($this->frame['show']) {
  2824.                     $style_pos .= 'margin-top:5px;'
  2825.                                .  'margin-left:5px;';
  2826.                 } else {
  2827.                     $style_pos .= 'margin-top:' . $data['top'] . 'px;'
  2828.                                .  'margin-left:' . $data['left'] . 'px;';
  2829.                 }
  2830.                 if ($width > 0) {
  2831.                     $style_pos .= 'width:' . $width . 'px;';
  2832.                 }
  2833.             } else {
  2834.                 $style_pos = 'top:' . $data['top'] . 'px;'
  2835.                            . 'left:' . $data['left'] . 'px;';
  2836.             }
  2837.             $style_cls = sprintf($data['class'], $name . $this->ident);
  2838.  
  2839.             switch ($data['type']) {
  2840.                 case HTML_PROGRESS2_LABEL_TEXT:
  2841.                     $strHtml .= $tabs
  2842.                              .  '<div id="plbl' . $name . $this->ident . '"'
  2843.                              .  ' style="position:absolute;' . $style_pos . '"'
  2844.                              .  ' class="' . $style_cls . '">'
  2845.                              .  $data['value']
  2846.                              .  '</div>'
  2847.                              .  PHP_EOL;
  2848.                     break;
  2849.                 case HTML_PROGRESS2_LABEL_BUTTON:
  2850.                     $strHtml .= $tabs
  2851.                              .  '<div><input id="plbl' . $name . $this->ident
  2852.                              .  '" type="button" value="' . $data['value']
  2853.                              .  '" style="position:absolute;' . $style_pos
  2854.                              .  '" class="' . $style_cls
  2855.                              .  '" onclick="' . $data['target']
  2856.                              .  '.location.href=\'' . $data['action'] . '\'" />'
  2857.                              .  '</div>'
  2858.                              .  PHP_EOL;
  2859.                     break;
  2860.                 case HTML_PROGRESS2_LABEL_STEP:
  2861.                     $strHtml .= $tabs
  2862.                              .  '<div id="plbl' . $name . $this->ident
  2863.                              .  '" style="position:absolute;' . $style_pos
  2864.                              .  '" class="' . $style_cls . '"> '
  2865.                              .  '</div>'
  2866.                              .  PHP_EOL;
  2867.                     break;
  2868.                 case HTML_PROGRESS2_LABEL_PERCENT:
  2869.                     $strHtml .= $tabs
  2870.                              .  '<div id="plbl' . $name . $this->ident . '"'
  2871.                              .  ' style="position:absolute;' .  $style_pos . '"'
  2872.                              .  ' class="' . $style_cls . '"> '
  2873.                              .  '</div>'
  2874.                              .  PHP_EOL;
  2875.                     break;
  2876.                 case HTML_PROGRESS2_LABEL_CROSSBAR:
  2877.                     $strHtml .= $tabs
  2878.                              .  '<div id="plbl' . $name . $this->ident . '"'
  2879.                              .  ' style="position:absolute;' .  $style_pos . '"'
  2880.                              .  ' class="' . $style_cls . '">'
  2881.                              .  $data['value']
  2882.                              .  '</div>'
  2883.                              .  PHP_EOL;
  2884.                     break;
  2885.             }
  2886.         }
  2887.  
  2888.         //  End of Top progress meter frame
  2889.         $strHtml .= $tabs
  2890.                  .  '</div>'
  2891.                  .  PHP_EOL;
  2892.  
  2893.         $placeHolders = array(
  2894.             '{_leftshift_}', '{_topshift_}', '{_heightshift_}',
  2895.             '{_cyshift_}', '{_rxshift_}'
  2896.         );
  2897.         $htmlElement = array(
  2898.             $leftshift, $topshift, $heightshift,
  2899.             ($topshift + $cyshift), ($leftshift + $progressAttr['width'])
  2900.         );
  2901.         $strHtml = str_replace($placeHolders, $htmlElement, $strHtml);
  2902.  
  2903.         return $strHtml;
  2904.     }
  2905.  
  2906.     /**
  2907.      * Renders the new value of progress meter.
  2908.      *
  2909.      * This method should be used only to display initial state of the progress meter.
  2910.      * Next steps to refresh display must use either moveStep() or moveNext() methods.
  2911.      *
  2912.      * @return     void
  2913.      * @since      2.0.0
  2914.      * @access     public
  2915.      */
  2916.     function display()
  2917.     {
  2918.         $this->_status = 'show';
  2919.         echo $this->toHtml();
  2920.     }
  2921.  
  2922.     /**
  2923.      * Hides the progress meter.
  2924.      *
  2925.      * Once the process is over this method provides a solution
  2926.      * to remove/hide the progress meter of the browser screen.
  2927.      *
  2928.      * @return     void
  2929.      * @since      2.0.0
  2930.      * @access     public
  2931.      */
  2932.     function hide()
  2933.     {
  2934.         $bar = '<script type="text/javascript">'
  2935.              .  'hideProgress("' . $this->ident . '");'
  2936.              .  '</script>';
  2937.  
  2938.         echo $bar . PHP_EOL;
  2939.     }
  2940.  
  2941.     /**
  2942.      * Delay execution.
  2943.      *
  2944.      * The HTML_Progress2::sleep() function delays program execution
  2945.      * for the given number of milliseconds.
  2946.      * This is the default user callback when none are defined.
  2947.      *
  2948.      * NOTE: The function {@link http://www.php.net/manual/en/function.usleep.php}
  2949.      *       did not work on Windows systems until PHP 5.0.0
  2950.      *
  2951.      * @return     void
  2952.      * @since      2.0.0
  2953.      * @access     public
  2954.      * @see        getAnimSpeed(), setAnimSpeed(), process()
  2955.      */
  2956.     function sleep()
  2957.     {
  2958.         // convert delay from milliseconds to microseconds
  2959.         $usecs = $this->animSpeed * 1000;
  2960.  
  2961.         if ((substr(PHP_OS, 0, 3) == 'WIN') && (substr(PHP_VERSION,0,1) < '5')) {
  2962.             for ($i = 0; $i < $usecs; $i++) {
  2963.             }
  2964.         } else {
  2965.             usleep($usecs);
  2966.         }
  2967.     }
  2968.  
  2969.     /**
  2970.      * Sets the user progress callback function.
  2971.      *
  2972.      * The process() function will call the user-callback defined here by this
  2973.      * setProgressHandler() method.
  2974.      *
  2975.      * The user-supplied progress function must return either positive
  2976.      * for a step progression, using moveStep() method,
  2977.      * or NULL for a standard progression, using moveNext() method.
  2978.      *
  2979.      * @param      mixed     $handler       Name of function or a class-method.
  2980.      *
  2981.      * @return     void
  2982.      * @since      2.0.0
  2983.      * @access     public
  2984.      * @throws     HTML_PROGRESS2_ERROR_INVALID_CALLBACK
  2985.      * @see        process()
  2986.      */
  2987.     function setProgressHandler($handler)
  2988.     {
  2989.         if (!is_callable($handler)) {
  2990.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_CALLBACK, 'warning',
  2991.                 array('var' => '$handler',
  2992.                       'element' => 'valid Class-Method/Function',
  2993.                       'was' => 'callback',
  2994.                       'paramnum' => 1));
  2995.         }
  2996.         $this->_callback = $handler;
  2997.     }
  2998.  
  2999.     /**
  3000.      * Performs the progress user process.
  3001.      *
  3002.      * This function call the user-specified progress function, defined by
  3003.      * setProgressHandler() method. Default callback is the HTML_Progress2::sleep() method.
  3004.      *
  3005.      * @return     mixed
  3006.      * @since      2.0.0
  3007.      * @access     public
  3008.      * @see        sleep(), setProgressHandler()
  3009.      */
  3010.     function process()
  3011.     {
  3012.         if ($this->_callback) {
  3013.             return call_user_func_array($this->_callback, array($this->value, &$this));
  3014.         } else {
  3015.             // when there is no valid user callback then default is to sleep a bit ...
  3016.             $this->sleep();
  3017.         }
  3018.     }
  3019.  
  3020.     /**
  3021.      * Runs the progress meter.
  3022.      *
  3023.      * This function accept both modes: indeterminate and determinate,
  3024.      * and execute all actions defined in the user callback identified by
  3025.      * setProgressHandler() method.
  3026.      *
  3027.      * All observers are also notified of main changes (start, stop meter).
  3028.      *
  3029.      * @return     void
  3030.      * @since      2.0.0
  3031.      * @access     public
  3032.      * @see        process(), setProgressHandler()
  3033.      */
  3034.     function run()
  3035.     {
  3036.         $this->_postNotification('onSubmit', array('handler' => __FUNCTION__, 'value' => $this->getValue()));
  3037.         do {
  3038.             $ret = $this->process();
  3039.             if ($this->getPercentComplete() == 1) {
  3040.                 if ($this->indeterminate) {
  3041.                     $this->setValue(0);
  3042.                 } else {
  3043.                     break;
  3044.                 }
  3045.             }
  3046.             if (is_null($ret)) {
  3047.                 $this->moveNext();
  3048.             } else {
  3049.                 $this->moveStep($ret);
  3050.             }
  3051.         } while (1);
  3052.         $this->_postNotification('onLoad', array('handler' => __FUNCTION__, 'value' => $this->getValue()));
  3053.     }
  3054.  
  3055.     /**
  3056.      * Returns the progress meter identifier.
  3057.      *
  3058.      * Each progress meter has its own identifier. That allows to display more than
  3059.      * only once meter at same time on same page.
  3060.      *
  3061.      * @return     string
  3062.      * @since      2.0.0
  3063.      * @access     public
  3064.      * @see        setIdent()
  3065.      */
  3066.     function getIdent()
  3067.     {
  3068.         return $this->ident;
  3069.     }
  3070.  
  3071.     /**
  3072.      * Sets the progress meter identifier.
  3073.      *
  3074.      * Each progress meter has its own identifier. That allows to display more than
  3075.      * only once meter at same time on same page.
  3076.      * If no identification string is given, then the default identifier will be
  3077.      * six first characters of md5 hash value of the current unix timestamp.
  3078.      *
  3079.      * @param      mixed     $ident         (optional) the new identification string.
  3080.      *
  3081.      * @since      2.0.0
  3082.      * @access     public
  3083.      * @see        getIdent()
  3084.      */
  3085.     function setIdent($ident = null)
  3086.     {
  3087.         if (is_null($ident)) {
  3088.             $this->ident = substr(md5(microtime()), 0, 6);
  3089.         } else {
  3090.             $this->ident = $ident;
  3091.         }
  3092.     }
  3093.  
  3094.     /**
  3095.      * Attachs a new observer.
  3096.      *
  3097.      * Adds a new observer to the Event Dispatcher that will listen
  3098.      * for all messages emitted by this HTML_Progress2 instance.
  3099.      *
  3100.      * @param      mixed     $callback      PHP callback that will act as listener
  3101.      * @param      string    $nName         Expected notification name, serves as a filter
  3102.      *
  3103.      * @return     void
  3104.      * @since      2.0.0
  3105.      * @access     public
  3106.      * @throws     HTML_PROGRESS2_ERROR_INVALID_CALLBACK,
  3107.      *             HTML_PROGRESS2_ERROR_INVALID_INPUT
  3108.      * @see        removeListener()
  3109.      */
  3110.     function addListener($callback, $nName = EVENT_DISPATCHER_GLOBAL)
  3111.     {
  3112.         if (!is_callable($callback)) {
  3113.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_CALLBACK, 'exception',
  3114.                 array('var' => '$callback',
  3115.                       'element' => 'valid Class-Method/Function',
  3116.                       'was' => 'callback',
  3117.                       'paramnum' => 1));
  3118.  
  3119.         } elseif (!is_string($nName)) {
  3120.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  3121.                 array('var' => '$nName',
  3122.                       'was' => gettype($nName),
  3123.                       'expected' => 'string',
  3124.                       'paramnum' => 2));
  3125.         }
  3126.  
  3127.         $this->dispatcher =& Event_Dispatcher::getInstance('ProgressMeter');
  3128.         $this->dispatcher->addObserver($callback, $nName);
  3129.         $this->_observerCount++;
  3130.     }
  3131.  
  3132.     /**
  3133.      * Removes a registered observer.
  3134.      *
  3135.      * Detachs a previously registered observer and remove the Event Dispatcher
  3136.      * if there is no more observer registered.
  3137.      *
  3138.      * @param      mixed     $callback      PHP callback that act as listener
  3139.      * @param      string    $nName         Expected notification name, serves as a filter
  3140.      *
  3141.      * @return     bool                     True if observer was removed, false otherwise
  3142.      * @since      2.0.0
  3143.      * @access     public
  3144.      * @throws     HTML_PROGRESS2_ERROR_INVALID_CALLBACK,
  3145.      *             HTML_PROGRESS2_ERROR_INVALID_INPUT
  3146.      * @see        addListener()
  3147.      */
  3148.     function removeListener($callback, $nName = EVENT_DISPATCHER_GLOBAL)
  3149.     {
  3150.         if (!is_callable($callback)) {
  3151.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_CALLBACK, 'exception',
  3152.                 array('var' => '$callback',
  3153.                       'element' => 'valid Class-Method/Function',
  3154.                       'was' => 'callback',
  3155.                       'paramnum' => 1));
  3156.  
  3157.         } elseif (!is_string($nName)) {
  3158.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  3159.                 array('var' => '$nName',
  3160.                       'was' => gettype($nName),
  3161.                       'expected' => 'string',
  3162.                       'paramnum' => 2));
  3163.         }
  3164.  
  3165.         $result = $this->dispatcher->removeObserver($callback, $nName);
  3166.  
  3167.         if ($result) {
  3168.             $this->_observerCount--;
  3169.             if ($this->_observerCount == 0) {
  3170.                 unset($this->dispatcher);
  3171.             }
  3172.         }
  3173.         return $result;
  3174.     }
  3175.  
  3176.     /**
  3177.      * Refresh the progress meter display.
  3178.      *
  3179.      * @param      integer   $value         new value of the progress meter
  3180.      *
  3181.      * @return     void
  3182.      * @since      2.0.0RC2
  3183.      * @access     private
  3184.      * @see        moveStep(), moveNext()
  3185.      */
  3186.     function _refreshDisplay($value)
  3187.     {
  3188.         static $determinate;
  3189.  
  3190.         foreach ($this->label as $name => $data) {
  3191.             switch($data['type']) {
  3192.             case HTML_PROGRESS2_LABEL_STEP:
  3193.                 if (!$this->indeterminate) {
  3194.                     $this->_changeLabelText($name, intval(ceil($value / $this->increment))
  3195.                                                  . '/'
  3196.                                                  . intval(ceil($this->maximum / $this->increment))
  3197.                     );
  3198.                 }
  3199.                 break;
  3200.             case HTML_PROGRESS2_LABEL_PERCENT:
  3201.                 if (!$this->indeterminate) {
  3202.                     $this->_changeLabelText($name, $this->getPercentComplete(false) . '%');
  3203.                 }
  3204.                 break;
  3205.             case HTML_PROGRESS2_LABEL_CROSSBAR:
  3206.                 $this->_changeCrossItem($name);
  3207.                 break;
  3208.             }
  3209.         }
  3210.  
  3211.         $bar  = ob_get_clean();
  3212.  
  3213.         if ($this->cellCount > 0) {
  3214.             $cellAmount = ($this->maximum - $this->minimum) / $this->cellCount;
  3215.  
  3216.             if ($this->indeterminate) {
  3217.                 if (isset($determinate)) {
  3218.                     $determinate++;
  3219.                     $progress = $determinate;
  3220.                 } else {
  3221.                     $progress = $determinate = 1;
  3222.                 }
  3223.             } else {
  3224.                 $progress = ($this->value - $this->minimum) / $cellAmount;
  3225.                 $determinate = 0;
  3226.             }
  3227.  
  3228.             $bar .= '<script type="text/javascript">'
  3229.                  .  'setProgress'
  3230.                  .  '("' . $this->ident . '",'
  3231.                  .  intval($progress) . ',' . $determinate . ',' . $this->cellCount
  3232.                  .  ');'
  3233.                  .  '</script>';
  3234.  
  3235.         } else {
  3236.  
  3237.             $position = $this->_computePosition();
  3238.  
  3239.             $orient = $this->orientation;
  3240.             $cssText = '';
  3241.             if ($orient == HTML_PROGRESS2_BAR_HORIZONTAL) {
  3242.                 if ($this->fillWay == 'reverse') {
  3243.                     $cssText .= 'left:' . $position['left'] . 'px;';
  3244.                 }
  3245.                 $cssText .= 'width:' . $position['width'] . 'px;';
  3246.             }
  3247.             if ($orient == HTML_PROGRESS2_BAR_VERTICAL) {
  3248.                 if ($this->fillWay == 'natural') {
  3249.                     $cssText .= 'top:' . $position['top'] . 'px;';
  3250.                 }
  3251.                 $cssText .= 'height:' . $position['height'] . 'px;';
  3252.             }
  3253.             $bar .= $this->_changeElementStyle('pbar', '', $cssText);
  3254.         }
  3255.         echo $bar . PHP_EOL;
  3256.         ob_start();
  3257.     }
  3258.  
  3259.     /**
  3260.      * Returns a horizontal progress bar structure as HTML.
  3261.      *
  3262.      * @return     string
  3263.      * @since      2.0.0
  3264.      * @access     private
  3265.      */
  3266.     function _getProgressHbar_toHtml()
  3267.     {
  3268.         $tabs = $this->_getTabs();
  3269.         $tab = $this->_getTab();
  3270.         $way_natural = ($this->fillWay == 'natural');
  3271.         $cellAttr = $this->getCellAttributes();
  3272.         $cellCls = sprintf($cellAttr['class'], $this->ident);
  3273.         $html = '';
  3274.  
  3275.         if ($way_natural) {
  3276.             $pos = $cellAttr['spacing'];
  3277.             for ($i = 0; $i < $this->cellCount; $i++) {
  3278.                 $html .= $tabs . $tab
  3279.                       .  '<div id="' . sprintf($cellAttr['id'], $i) . $this->ident . '"'
  3280.                       .  ' class="' . $cellCls . 'I"'
  3281.                       .  ' style="position:absolute;'
  3282.                       .  'left:' . $pos . 'px;'
  3283.                       .  'top:' . $cellAttr['spacing'] . 'px;';
  3284.                 if (isset($cellAttr[$i])) {
  3285.                     $html .= 'color:' . $cellAttr[$i]['color'] . ';';
  3286.                 }
  3287.                 $html .= '"></div>' . PHP_EOL;
  3288.  
  3289.                 $pos += ($cellAttr['width'] + $cellAttr['spacing']);
  3290.             }
  3291.         } else {
  3292.             $pos = $cellAttr['spacing'];
  3293.             for ($i = $this->cellCount - 1; $i >= 0; $i--) {
  3294.                 $html .= $tabs . $tab
  3295.                       .  '<div id="' . sprintf($cellAttr['id'], $i) . $this->ident . '"'
  3296.                       .  ' class="' . $cellCls . 'I"'
  3297.                       .  ' style="position:absolute;'
  3298.                       .  'left:' . $pos . 'px;'
  3299.                       .  'top:' . $cellAttr['spacing'] . 'px;';
  3300.                 if (isset($cellAttr[$i])) {
  3301.                     $html .= 'color:' . $cellAttr[$i]['color'] . ';';
  3302.                 }
  3303.                 $html .= '"></div>' . PHP_EOL;
  3304.  
  3305.                 $pos += ($cellAttr['width'] + $cellAttr['spacing']);
  3306.             }
  3307.         }
  3308.         return $html;
  3309.     }
  3310.  
  3311.     /**
  3312.      * Returns a vertical progress bar structure as HTML.
  3313.      *
  3314.      * @return     string
  3315.      * @since      2.0.0
  3316.      * @access     private
  3317.      */
  3318.     function _getProgressVbar_toHtml()
  3319.     {
  3320.         $tabs = $this->_getTabs();
  3321.         $tab = $this->_getTab();
  3322.         $way_natural = ($this->fillWay == 'natural');
  3323.         $cellAttr = $this->getCellAttributes();
  3324.         $cellCls = sprintf($cellAttr['class'], $this->ident);
  3325.         $html = '';
  3326.  
  3327.         if ($way_natural) {
  3328.             $pos = $cellAttr['spacing'];
  3329.             for ($i = $this->cellCount - 1; $i >= 0; $i--) {
  3330.                 $html .= $tabs . $tab
  3331.                       .  '<div id="' . sprintf($cellAttr['id'], $i) . $this->ident . '"'
  3332.                       .  ' class="' . $cellCls . 'I"'
  3333.                       .  ' style="position:absolute;'
  3334.                       .  'left:' . $cellAttr['spacing'] . 'px;'
  3335.                       .  'top:' . $pos . 'px;';
  3336.                 if (isset($cellAttr[$i])) {
  3337.                     $html .= 'color:' . $cellAttr[$i]['color'] . ';';
  3338.                 }
  3339.                 $html .= '"></div>' . PHP_EOL;
  3340.  
  3341.                 $pos += ($cellAttr['height'] + $cellAttr['spacing']);
  3342.             }
  3343.         } else {
  3344.             $pos = $cellAttr['spacing'];
  3345.             for ($i = 0; $i < $this->cellCount; $i++) {
  3346.                 $html .= $tabs . $tab
  3347.                       .  '<div id="' . sprintf($cellAttr['id'], $i) . $this->ident . '"'
  3348.                       .  ' class="' . $cellCls . 'I"'
  3349.                       .  ' style="position:absolute;'
  3350.                       .  'left:' . $cellAttr['spacing'] . 'px;'
  3351.                       .  'top:' . $pos . 'px;';
  3352.                 if (isset($cellAttr[$i])) {
  3353.                     $html .= 'color:' . $cellAttr[$i]['color'] . ';';
  3354.                 }
  3355.                 $html .= '"></div>' . PHP_EOL;
  3356.  
  3357.                 $pos += ($cellAttr['height'] + $cellAttr['spacing']);
  3358.             }
  3359.         }
  3360.         return $html;
  3361.     }
  3362.  
  3363.     /**
  3364.      * Returns a polygonal progress structure as HTML.
  3365.      *
  3366.      * @return     string
  3367.      * @since      2.0.0
  3368.      * @access     private
  3369.      */
  3370.     function _getProgressPolygonal_toHtml()
  3371.     {
  3372.         $tabs = $this->_getTabs();
  3373.         $tab = $this->_getTab();
  3374.         $way_natural = ($this->fillWay == 'natural');
  3375.         $cellAttr = $this->getCellAttributes();
  3376.         $cellCls = sprintf($cellAttr['class'], $this->ident);
  3377.         $coord = $this->getCellCoordinates();
  3378.         $html = '';
  3379.  
  3380.         if ($way_natural) {
  3381.             for ($i = 0; $i < $this->cellCount; $i++) {
  3382.                 $top  = $coord[$i][0] * $cellAttr['width'];
  3383.                 $left = $coord[$i][1] * $cellAttr['height'];
  3384.                 $html .= $tabs . $tab
  3385.                       .  '<div id="' . sprintf($cellAttr['id'], $i) . $this->ident . '"'
  3386.                       .  ' class="' . $cellCls . 'I"'
  3387.                       .  ' style="position:absolute;'
  3388.                       .  'left:' . $left . 'px;'
  3389.                       .  'top:' . $top . 'px;';
  3390.                 if (isset($cellAttr[$i])) {
  3391.                     $html .= 'color:' . $cellAttr[$i]['color'] . ';';
  3392.                 }
  3393.                 $html .= '"></div>' . PHP_EOL;
  3394.             }
  3395.         } else {
  3396.             $c = count($coord) - 1;
  3397.             for ($i = 0; $i < $this->cellCount; $i++) {
  3398.                 $top  = $coord[$c-$i][0] * $cellAttr['width'];
  3399.                 $left = $coord[$c-$i][1] * $cellAttr['height'];
  3400.                 $html .= $tabs . $tab
  3401.                       .  '<div id="' . sprintf($cellAttr['id'], $i) . $this->ident . '"'
  3402.                       .  ' class="' . $cellCls . 'I"'
  3403.                       .  ' style="position:absolute;'
  3404.                       .  'left:' . $left . 'px;'
  3405.                       .  'top:' . $top . 'px;';
  3406.                 if (isset($cellAttr[$i])) {
  3407.                     $html .= 'color:' . $cellAttr[$i]['color'] . ';';
  3408.                 }
  3409.                 $html .= '"></div>' . PHP_EOL;
  3410.             }
  3411.         }
  3412.  
  3413.         return $html;
  3414.     }
  3415.  
  3416.     /**
  3417.      * Returns a circle progress structure as HTML.
  3418.      *
  3419.      * @return     string
  3420.      * @since      2.0.0
  3421.      * @access     private
  3422.      */
  3423.     function _getProgressCircle_toHtml()
  3424.     {
  3425.         $tabs = $this->_getTabs();
  3426.         $tab = $this->_getTab();
  3427.         $way_natural = ($this->fillWay == 'natural');
  3428.         $cellAttr = $this->getCellAttributes();
  3429.         $cellCls = sprintf($cellAttr['class'], $this->ident);
  3430.         $html = '';
  3431.  
  3432.         if ($way_natural) {
  3433.             for ($i = 0; $i < $this->cellCount; $i++) {
  3434.                 $html .= $tabs . $tab
  3435.                       .  '<div id="' . sprintf($cellAttr['id'], $i) . $this->ident . '"'
  3436.                       .  ' class="' . $cellCls . 'I"'
  3437.                       .  ' style="position:absolute;left:0;top:0;'
  3438.                       .  '"><img src="' . $cellAttr[$i+1]['background-image']
  3439.                       .  '" border="0" alt="" />'
  3440.                       .  '</div>'
  3441.                       .  PHP_EOL;
  3442.             }
  3443.         } else {
  3444.             for ($i = 0; $i < $this->cellCount; $i++) {
  3445.                 $html .= $tabs . $tab
  3446.                       .  '<div id="' . sprintf($cellAttr['id'], $i) . $this->ident . '"'
  3447.                       .  ' class="' . $cellCls . 'I"'
  3448.                       .  ' style="position:absolute;left:0;top:0;'
  3449.                       .  '"><img src="' . $cellAttr[$i+1]['background-image']
  3450.                       .  '" border="0" alt="" />'
  3451.                       .  '</div>'
  3452.                       .  PHP_EOL;
  3453.             }
  3454.         }
  3455.         return $html;
  3456.     }
  3457.  
  3458.     /**
  3459.      * Computes all coordinates of a standard polygon (square or rectangle).
  3460.      *
  3461.      * @param      integer   $w             Polygon width
  3462.      * @param      integer   $h             Polygon height
  3463.      *
  3464.      * @return     array
  3465.      * @since      2.0.0
  3466.      * @access     private
  3467.      * @see        setCellCoordinates()
  3468.      */
  3469.     function _computeCoordinates($w, $h)
  3470.     {
  3471.         $coord = array();
  3472.  
  3473.         for ($y=0; $y<$h; $y++) {
  3474.             if ($y == 0) {
  3475.                 // creates top side line
  3476.                 for ($x=0; $x<$w; $x++) {
  3477.                     $coord[] = array($y, $x);
  3478.                 }
  3479.             } elseif ($y == ($h-1)) {
  3480.                 // creates bottom side line
  3481.                 for ($x=($w-1); $x>0; $x--) {
  3482.                     $coord[] = array($y, $x);
  3483.                 }
  3484.                 // creates left side line
  3485.                 for ($i=($h-1); $i>0; $i--) {
  3486.                     $coord[] = array($i, 0);
  3487.                 }
  3488.             } else {
  3489.                 // creates right side line
  3490.                 $coord[] = array($y, $w - 1);
  3491.             }
  3492.         }
  3493.         return $coord;
  3494.     }
  3495.  
  3496.     /**
  3497.      * Updates the new size of progress bar, depending of cell size, cell count
  3498.      * and border width.
  3499.      *
  3500.      * @since      2.0.0
  3501.      * @access     private
  3502.      * @see        setOrientation(), setCellCount(), setCellAttributes(),
  3503.      *             setBorderAttributes()
  3504.      */
  3505.     function _updateProgressSize()
  3506.     {
  3507.         if ($this->cellCount == 0) {
  3508.             return;
  3509.         }
  3510.  
  3511.         $cell_width   = $this->cell['width'];
  3512.         $cell_height  = $this->cell['height'];
  3513.         $cell_spacing = $this->cell['spacing'];
  3514.  
  3515.         $border_width = $this->border['width'];
  3516.  
  3517.         $cell_count = $this->cellCount;
  3518.  
  3519.         if ($this->orientation == HTML_PROGRESS2_BAR_HORIZONTAL) {
  3520.             $w = ($cell_count * ($cell_width + $cell_spacing)) + $cell_spacing;
  3521.             $h = $cell_height + (2 * $cell_spacing);
  3522.         }
  3523.         if ($this->orientation == HTML_PROGRESS2_BAR_VERTICAL) {
  3524.             $w  = $cell_width + (2 * $cell_spacing);
  3525.             $h  = ($cell_count * ($cell_height + $cell_spacing)) + $cell_spacing;
  3526.         }
  3527.         if ($this->orientation == HTML_PROGRESS2_POLYGONAL) {
  3528.             $w  = $cell_width * $this->_xgrid;
  3529.             $h  = $cell_height * $this->_ygrid;
  3530.         }
  3531.         if ($this->orientation == HTML_PROGRESS2_CIRCLE) {
  3532.             $w  = $cell_width;
  3533.             $h  = $cell_height;
  3534.         }
  3535.  
  3536.         $attr = array ('width' => $w, 'height' => $h);
  3537.  
  3538.         $this->_updateAttrArray($this->_progress, $attr);
  3539.     }
  3540.  
  3541.     /**
  3542.      * Calculate the new position in pixel of the progress bar value.
  3543.      *
  3544.      * @return     void
  3545.      * @since      2.0.0
  3546.      * @access     private
  3547.      */
  3548.     function _computePosition()
  3549.     {
  3550.         $orient = $this->orientation;
  3551.         $progressAttr = $this->getProgressAttributes();
  3552.         $min = $this->minimum;
  3553.         $max = $this->maximum;
  3554.         $step = $this->value;
  3555.         $padding = 0;
  3556.  
  3557.         if ($orient == HTML_PROGRESS2_BAR_HORIZONTAL) {
  3558.             if ($this->fillWay == 'natural') {
  3559.                 $direction = 'right';
  3560.             } else {
  3561.                 $direction = 'left';
  3562.             }
  3563.         } else {
  3564.             if ($this->fillWay == 'natural') {
  3565.                 $direction = 'up';
  3566.             } else {
  3567.                 $direction = 'down';
  3568.             }
  3569.         }
  3570.  
  3571.         switch ($direction) {
  3572.             case 'right':
  3573.             case 'left':
  3574.                 $bar = $progressAttr['width'];
  3575.                 break;
  3576.             case 'down':
  3577.             case 'up':
  3578.                 $bar = $progressAttr['height'];
  3579.                 break;
  3580.         }
  3581.         $pixel = round(($step - $min) * ($bar - ($padding * 2)) / ($max - $min));
  3582.         if ($step <= $min) {
  3583.             $pixel = 0;
  3584.         }
  3585.         if ($step >= $max) {
  3586.             $pixel = $bar - ($padding * 2);
  3587.         }
  3588.  
  3589.         switch ($direction) {
  3590.             case 'right':
  3591.                 $position['left'] = $padding;
  3592.                 $position['top'] = $padding;
  3593.                 $position['width'] = $pixel;
  3594.                 $position['height'] = $progressAttr['height'] - ($padding * 2);
  3595.                 break;
  3596.             case 'left':
  3597.                 $position['left'] = $progressAttr['width'] - $padding - $pixel;
  3598.                 $position['top'] = $padding;
  3599.                 $position['width'] = $pixel;
  3600.                 $position['height'] = $progressAttr['height'] - ($padding * 2);
  3601.                 break;
  3602.             case 'down':
  3603.                 $position['left'] = $padding;
  3604.                 $position['top'] = $padding;
  3605.                 $position['width'] = $progressAttr['width'] - ($padding * 2);
  3606.                 $position['height'] = $pixel;
  3607.                 break;
  3608.             case 'up':
  3609.                 $position['left'] = $padding;
  3610.                 $position['top'] = $progressAttr['height'] - $padding - $pixel;
  3611.                 $position['width'] = $progressAttr['width'] - ($padding * 2);
  3612.                 $position['height'] = $pixel;
  3613.                 break;
  3614.         }
  3615.         return $position;
  3616.     }
  3617.  
  3618.     /**
  3619.      * Sends a DOM command (emulate firstChild.nodeValue) through a javascript function
  3620.      * to change label value of a progress bar's element.
  3621.      *
  3622.      * @param      string    $element       element name (label id.)
  3623.      * @param      string    $text          element value (label content)
  3624.      *
  3625.      * @return     void
  3626.      * @since      2.0.0
  3627.      * @access     private
  3628.      */
  3629.     function _changeLabelText($element, $text)
  3630.     {
  3631.         $cmd = '<script type="text/javascript">'
  3632.              . 'setLabelText'
  3633.              . '("' . $this->ident . '","' . $element . '","' . $text . '");'
  3634.              . '</script>';
  3635.  
  3636.         echo $cmd;
  3637.     }
  3638.  
  3639.     /**
  3640.      * Sends a DOM command through a javascript function
  3641.      * to change the next frame animation of a cross bar's element.
  3642.      *
  3643.      * @param      string    $element       element name (cross id.)
  3644.      *
  3645.      * @return     string
  3646.      * @since      2.0.0
  3647.      * @access     private
  3648.      */
  3649.     function _changeCrossItem($element)
  3650.     {
  3651.         $cmd = '<script type="text/javascript">'
  3652.              . 'setRotaryCross'
  3653.              . '("' . $this->ident . '","' . $element . '");'
  3654.              . '</script>';
  3655.  
  3656.         echo $cmd;
  3657.     }
  3658.  
  3659.     /**
  3660.      * Sends a DOM command (emulate cssText attribute) through a javascript function
  3661.      * to change styles of a progress bar's element.
  3662.      *
  3663.      * @param      string    $prefix        prefix identifier of the element
  3664.      * @param      string    $element       element name (label id.)
  3665.      * @param      string    $styles        styles of a DOM element
  3666.      *
  3667.      * @return     string
  3668.      * @since      2.0.0
  3669.      * @access     private
  3670.      */
  3671.     function _changeElementStyle($prefix, $element, $styles)
  3672.     {
  3673.         $cmd = '<script type="text/javascript">'
  3674.              . 'setElementStyle'
  3675.              . '("' . $prefix . '","' . $element . '","' . $this->ident . '","' . $styles . '");'
  3676.              . '</script>';
  3677.  
  3678.         return $cmd;
  3679.     }
  3680.  
  3681.     /**
  3682.      * Post a new notification to all observers registered.
  3683.      * This notification occured only if a dispatcher exists. That means if
  3684.      * at least one observer was registered.
  3685.      *
  3686.      * @param      string    $event         Name of the notification handler
  3687.      * @param      array     $info          (optional) Additional information about the notification
  3688.      *
  3689.      * @return     void
  3690.      * @since      2.0.0RC2
  3691.      * @access     private
  3692.      */
  3693.     function _postNotification($event, $info = array())
  3694.     {
  3695.         if (isset($this->dispatcher)) {
  3696.             $info['sender'] = get_class($this);
  3697.             $info['time']   = microtime();
  3698.             $this->dispatcher->post($this, $event, $info);
  3699.         }
  3700.     }
  3701.  
  3702.     /**
  3703.      * Initialize Error Handler
  3704.      *
  3705.      * Parameter '$prefs' contains a hash of options to define the error handler.
  3706.      * You may find :
  3707.      *  'message_callback'  A callback to generate message body.
  3708.      *                      Default is:  HTML_Progress2_Error::_msgCallback()
  3709.      *  'context_callback'  A callback to generate context of error.
  3710.      *                      Default is:  HTML_Progress2_Error::getBacktrace()
  3711.      *  'push_callback'     A callback to determine whether to allow an error
  3712.      *                      to be pushed or logged.
  3713.      *                      Default is:  HTML_Progress2_Error::_handleError()
  3714.      *  'error_handler'     A callback to manage all error raised.
  3715.      *                      Default is:  HTML_Progress2::_errorHandler()
  3716.      *  'handler'           Hash of params to configure all handlers (display, file, mail ...)
  3717.      *                      There are only a display handler by default with options below:
  3718.      *
  3719.      * @param      array     $prefs         hash of params to configure error handler
  3720.      *
  3721.      * @return     void
  3722.      * @since      2.0.0
  3723.      * @access     private
  3724.      */
  3725.     function _initErrorHandler($prefs = array())
  3726.     {
  3727.         // error message mapping callback
  3728.         if (isset($prefs['message_callback']) && is_callable($prefs['message_callback'])) {
  3729.             $this->_callback_message = $prefs['message_callback'];
  3730.         } else {
  3731.             $this->_callback_message = array('HTML_Progress2_Error', '_msgCallback');
  3732.         }
  3733.  
  3734.         // error context mapping callback
  3735.         if (isset($prefs['context_callback']) && is_callable($prefs['context_callback'])) {
  3736.             $this->_callback_context = $prefs['context_callback'];
  3737.         } else {
  3738.             $this->_callback_context = array('HTML_Progress2_Error', 'getBacktrace');
  3739.         }
  3740.  
  3741.         // determine whether to allow an error to be pushed or logged
  3742.         if (isset($prefs['push_callback']) && is_callable($prefs['push_callback'])) {
  3743.             $this->_callback_push = $prefs['push_callback'];
  3744.         } else {
  3745.             $this->_callback_push = array('HTML_Progress2_Error', '_handleError');
  3746.         }
  3747.  
  3748.         // default error handler will use PEAR_Error
  3749.         if (isset($prefs['error_handler']) && is_callable($prefs['error_handler'])) {
  3750.             $this->_callback_errorhandler = $prefs['error_handler'];
  3751.         } else {
  3752.             $this->_callback_errorhandler = array(&$this, '_errorHandler');
  3753.         }
  3754.  
  3755.         // any handler-specific settings
  3756.         if (isset($prefs['handler'])) {
  3757.             $this->_errorhandler_options = $prefs['handler'];
  3758.         }
  3759.     }
  3760.  
  3761.     /**
  3762.      * Standard error handler that will use PEAR_Error object
  3763.      *
  3764.      * To improve performances, the PEAR.php file is included dynamically.
  3765.      * The file is so included only when an error is triggered. So, in most
  3766.      * cases, the file isn't included and perfs are much better.
  3767.      *
  3768.      * @param      integer   $code          Error code
  3769.      * @param      string    $level         Error level
  3770.      * @param      array     $params        Associative array of error parameters
  3771.      *
  3772.      * @return     PEAR_Error
  3773.      * @since      2.0.0
  3774.      * @access     private
  3775.      */
  3776.     function _errorHandler($code, $level, $params)
  3777.     {
  3778.         require_once 'HTML/Progress2/Error.php';
  3779.  
  3780.         $mode = call_user_func($this->_callback_push, $code, $level);
  3781.  
  3782.         $message = call_user_func($this->_callback_message, $code, $params);
  3783.         $userinfo['level'] = $level;
  3784.  
  3785.         if (isset($this->_errorhandler_options['display'])) {
  3786.             $userinfo['display'] = $this->_errorhandler_options['display'];
  3787.         } else {
  3788.             $userinfo['display'] = array();
  3789.         }
  3790.         if (isset($this->_errorhandler_options['log'])) {
  3791.             $userinfo['log'] = $this->_errorhandler_options['log'];
  3792.         } else {
  3793.             $userinfo['log'] = array();
  3794.         }
  3795.  
  3796.         return PEAR::raiseError($message, $code, $mode, null, $userinfo, 'HTML_Progress2_Error');
  3797.     }
  3798.  
  3799.     /**
  3800.      * A basic wrapper around the default PEAR_Error object.
  3801.      *
  3802.      * This method throws any internal API error that could be raised
  3803.      * due to a wrong programming. It will use your error handler system defined
  3804.      * at class construction (by first argument).
  3805.      *
  3806.      * @return     mixed
  3807.      * @since      2.0.0
  3808.      * @access     public
  3809.      * @see        _errorHandler()
  3810.      */
  3811.     function raiseError()
  3812.     {
  3813.         $args = func_get_args();
  3814.         $err = call_user_func_array($this->_callback_errorhandler, $args);
  3815.         if (is_null($err)) {
  3816.             $err = array('code' => $args[0], 'level' => $args[1], 'params' => $args[2]);
  3817.         }
  3818.         array_push($this->_errorstack, $err);
  3819.         return $err;
  3820.     }
  3821.  
  3822.     /**
  3823.      * Determine whether there are errors into the HTML_Progress2 stack.
  3824.      *
  3825.      * This function gave you ability to be aware of API errors presence
  3826.      * in user scripts.
  3827.      *
  3828.      * @return     integer
  3829.      * @since      2.0.0
  3830.      * @access     public
  3831.      * @see        getError(), raiseError()
  3832.      */
  3833.     function hasErrors()
  3834.     {
  3835.         return count($this->_errorstack);
  3836.     }
  3837.  
  3838.     /**
  3839.      * Pop an error off of the HTML_Progress2 stack.
  3840.      *
  3841.      * Get all error data (code, message, level, context) from an object (PEAR_Error, ...)
  3842.      * or a simple php array.
  3843.      *
  3844.      * @return     false|array|PEAR_Error
  3845.      * @since      2.0.0
  3846.      * @access     public
  3847.      * @see        hasErrors(), raiseError()
  3848.      */
  3849.     function getError()
  3850.     {
  3851.         return @array_shift($this->_errorstack);
  3852.     }
  3853. }
  3854. ?>